Initial checkin of upstream version 4.09.
Signed-off-by: Thomas Hochstein <thh@inter.net>
This commit is contained in:
		
						commit
						ac7e2c541a
					
				
					 47 changed files with 8045 additions and 0 deletions
				
			
		
							
								
								
									
										484
									
								
								CHANGES
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										484
									
								
								CHANGES
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,484 @@
 | 
				
			||||||
 | 
					UseVoteGer Versionshistorie (aktuelle Version: 4.09, released 07.10.2007)
 | 
				
			||||||
 | 
					=========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TODO:
 | 
				
			||||||
 | 
					- aussortieren von Bounces aus Stimmenliste
 | 
				
			||||||
 | 
					- Unterstuetzung von Maildir
 | 
				
			||||||
 | 
					- [Zugschlus] ich fänd es klasse, wenn man eine Kopie des Wahlscheines ins
 | 
				
			||||||
 | 
					Abstimmungsverzeichnis legt und Usevote einem dann auf Abruf ein diff
 | 
				
			||||||
 | 
					oder wdiff zwischen Sollwahlschein und wirklich eingreichtem
 | 
				
			||||||
 | 
					Wahlschein macht. Auf diese Weise erwischt man auch kleine Änderungen
 | 
				
			||||||
 | 
					am Datenschutzhinweis (da bin ich eben in eine Falle von th-h getappt).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.09 (14.09.2007):
 | 
				
			||||||
 | 
					- "votefile"-Option in usevote.cfg an passendere Stelle verschoben und
 | 
				
			||||||
 | 
					  den Kommentar korrigiert (natuerlich gilt pop3=0 als Bedingung, nicht
 | 
				
			||||||
 | 
					  etwa wie vorher angegeben smtp=0)
 | 
				
			||||||
 | 
					- Fehler in Template für Ergebnisausgabe korrigiert (fehlendes Newline
 | 
				
			||||||
 | 
					  nach umgebrochenen Abstimmungspunkten)
 | 
				
			||||||
 | 
					- Fehler in Doku der Kommandozeilenoptionen von uvcount.pl behoben
 | 
				
			||||||
 | 
					  (--voters statt --votes)
 | 
				
			||||||
 | 
					- Date-Header in Englisch erzeugen (statt in eingestellter locale)
 | 
				
			||||||
 | 
					  (verwendet nun Modul Email::Date)
 | 
				
			||||||
 | 
					- Message-ID-Header selbst erzeugen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.08 (06.10.2005):
 | 
				
			||||||
 | 
					- beim Ignorieren von Regelverletzungen (im Menue mit "Stimmen OK" bestaetigt)
 | 
				
			||||||
 | 
					  wird jetzt keine (dann ja unangebrachte) Fehlermail mehr verschickt.
 | 
				
			||||||
 | 
					- neuer Buchstabe I bzw. i in usevote.rul, der auf NEIN und ENTHALTUNG matcht.
 | 
				
			||||||
 | 
					  Damit lässt sich eine Stichwahl realisieren, bei der nur für eine von
 | 
				
			||||||
 | 
					  zwei Möglichkeiten mit JA gestimmt werden darf und im anderen Feld entweder
 | 
				
			||||||
 | 
					  NEIN oder ENTHALTUNG (bzw. garnichts, was Enthaltung enspricht)
 | 
				
			||||||
 | 
					  eingetragen werden muss.
 | 
				
			||||||
 | 
					- analog neuer Buchstabe H bzw. h für JA/ENTHALTUNG, der Vollstaendigkeit halber
 | 
				
			||||||
 | 
					- uvvote.pl sortiert die Liste der Ergebnisdateien jetzt vorm Zusammenfuegen
 | 
				
			||||||
 | 
					  zur neuen ergebnis.alle, so dass die Reihenfolge auf jeden Fall stimmt,
 | 
				
			||||||
 | 
					  auch wenn das System die Dateien unsortiert liefert
 | 
				
			||||||
 | 
					- wenn uvcount.pl in der ergebnis.alle auf eine falsche Anzahl von Abstimmungspunkten
 | 
				
			||||||
 | 
					  bei einer Stimme trifft (z.B. versehentlich Leerzeichen oder Buchstabe 
 | 
				
			||||||
 | 
					  am Ende einer Zeile zuviel, wenn manuell editiert wurde), bricht es ab und
 | 
				
			||||||
 | 
					  weist auf die fehlerhafte Stimme hin. Vorher wurde das als weiterer
 | 
				
			||||||
 | 
					  Abstimmungspunkt gezählt.
 | 
				
			||||||
 | 
					- Doku ergänzt: "envelopefrom" bezieht sich nur auf SMTP, ansonsten muss
 | 
				
			||||||
 | 
					  das in "mailcmd" konfiguriert werden
 | 
				
			||||||
 | 
					- Bug bei Eingruppenmodus behoben: Es wurde immer das selbe ausgegeben,
 | 
				
			||||||
 | 
					  unabhaengig vom Ergebnis (keine 60 Stimmen, keine 2/3 Mehrheit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.07 (26.09.2004):
 | 
				
			||||||
 | 
					- wenn "nodup=1" gesetzt war, wurden auch keine Annullierungen aussortiert.
 | 
				
			||||||
 | 
					  Ausserdem wurde ansonsten der Wahlleiter unnoetig gefragt, welche
 | 
				
			||||||
 | 
					  Stimme aussortiert werden soll, auch wenn letztlich beide annulliert
 | 
				
			||||||
 | 
					  waren (die Annullierung aber erst spaeter eingegangen war).
 | 
				
			||||||
 | 
					  Um diese Fehler zu beheben, wurde ein zusaetzlicher Verarbeitungsschritt
 | 
				
			||||||
 | 
					  in uvcount.pl eingefuehrt, der sich nur um Annullierungen kuemmert und
 | 
				
			||||||
 | 
					  die gleich am Anfang verarbeitet.
 | 
				
			||||||
 | 
					- es ist jetzt auch moeglich, nach einer Annullierung mit derselben
 | 
				
			||||||
 | 
					  Mailadresse nochmal abzustimmen. Vorher wurde so eine Stimmabgabe
 | 
				
			||||||
 | 
					  durch die vorher erfolgte Annullierung mit erfasst
 | 
				
			||||||
 | 
					- Template result-proportional korrigiert. Es kam zu Darstellungsfehlern
 | 
				
			||||||
 | 
					  bei umgebrochenen Gruppennamen/Wahlgegenstaenden (falsche Einrueckung,
 | 
				
			||||||
 | 
					  falscher Umbruch)
 | 
				
			||||||
 | 
					- Formatfunktion 'generate-date-header' fuer Templates eingefuehrt
 | 
				
			||||||
 | 
					- Template 'mailheader' um Date-Header ergaenzt
 | 
				
			||||||
 | 
					- chomp auf Message-ID nur noch machen, wenn eine Message-ID vorhanden ist
 | 
				
			||||||
 | 
					  (gibt sonst Warnung wegen undef)
 | 
				
			||||||
 | 
					- wenn die Option "mailcc" gesetzt ist, wurden die Hochkommata in der
 | 
				
			||||||
 | 
					  domail-Datei (siehe Changelog von Version 4.06) um beide Adressen gesetzt.
 | 
				
			||||||
 | 
					  Jetzt wird in einer Schleife jede Adresse einzeln gequotet.
 | 
				
			||||||
 | 
					- RegEx fuer Realnamenserkennung um den Bindestrich erweitert, damit
 | 
				
			||||||
 | 
					  Doppelnamen anerkannt werden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.06 (18.06.2004):
 | 
				
			||||||
 | 
					- Es werden nun "In-Reply-To:" und "References:" Header in den
 | 
				
			||||||
 | 
					  generierten Mails erzeugt
 | 
				
			||||||
 | 
					- beim Schreiben des domail-Scripts (Verschicken von Mails ohne SMTP)
 | 
				
			||||||
 | 
					  wurde ein fehlerhafter Zeilenumbruch eingefuegt
 | 
				
			||||||
 | 
					- Leerzeichen am Zeilenende in der usevote.cfg hatten dazu geführt,
 | 
				
			||||||
 | 
					  dass Einstellungen nicht korrekt eingelesen wurden. Jetzt werden
 | 
				
			||||||
 | 
					  beim Einlesen der Konfiguration solche Leerzeichen gelöscht (außer
 | 
				
			||||||
 | 
					  wenn der Teil rechts vom Gleichzeichen durch Anführungsstriche umschlossen
 | 
				
			||||||
 | 
					  ist)
 | 
				
			||||||
 | 
					- Mailadresse und Waehlername werden jetzt korrekt zurueckgesetzt, so
 | 
				
			||||||
 | 
					  dass bei fehlendem From-Header nicht noch die Daten der vorherigen Mail
 | 
				
			||||||
 | 
					  in den Variablen stehen
 | 
				
			||||||
 | 
					- Mailadresse wird nun in Hochkommata eingeschlossen, wenn sie in die
 | 
				
			||||||
 | 
					  "domail"-Datei geschrieben wird (bei smtp=0 in usevote.cfg), damit
 | 
				
			||||||
 | 
					  Shell-Metazeichen nicht beim Ausfuehren des MTA interpretiert und damit
 | 
				
			||||||
 | 
					  die Mailadresse veraendert bzw. potentiell schaedlicher Code ausgefuehrt
 | 
				
			||||||
 | 
					  wird
 | 
				
			||||||
 | 
					- Es ist jetzt moeglich, bei der Warnung "Es wurden nicht alle Fehler behoben,
 | 
				
			||||||
 | 
					  der Waehler wird eine Fehlermail erhalten" zurueck ins Menue zu gehen
 | 
				
			||||||
 | 
					  und die Fehler doch noch zu beheben
 | 
				
			||||||
 | 
					- in uvcfv.pl (Verschicken von personalisierten Wahlscheinen) einige
 | 
				
			||||||
 | 
					  Bugs behoben [warum hatte das ueberhaupt so funktioniert? Schroedinger
 | 
				
			||||||
 | 
					  laesst gruessen.] und den Hinweistext "Wahlschein wurde bereits einmal
 | 
				
			||||||
 | 
					  zugeschickt" aus dem Perlcode in das Template ballot-personal verlagert
 | 
				
			||||||
 | 
					- mittels "uvcfv.pl -t" laesst sich jetzt ein personalisierter
 | 
				
			||||||
 | 
					  Dummy-Wahlschein ausgeben (wenn "personal=1" in usevote.cfg), um ihn
 | 
				
			||||||
 | 
					  vorab der dana-Moderation zur Pruefung zukommen lassen zu koennen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.05 (27.12.2003):
 | 
				
			||||||
 | 
					- Aendern von Mailadressen oder Namen im Menue fuehrte zu "keine Scheinkennung"
 | 
				
			||||||
 | 
					  Fehlern, auch wenn die personalisierten Wahlscheine nicht aktiviert waren
 | 
				
			||||||
 | 
					  (personal=0 in usevote.cfg). 
 | 
				
			||||||
 | 
					- Fehler beim Verarbeiten von Mailbox-Files behoben. In den letzten
 | 
				
			||||||
 | 
					  Versionen funktionierte nur POP3.
 | 
				
			||||||
 | 
					- In Wahlschein-Templates "kann fuer ungueltig erklaert werden" in
 | 
				
			||||||
 | 
					  "wird fuer ungueltig erklaert werden" geaendert (bei falschem Realname)
 | 
				
			||||||
 | 
					- kosmetische Aenderungen in Templates (Anpassung an neue Rechtschreibung,
 | 
				
			||||||
 | 
					  Entfernung von Umlauten fuer einheitliches Schriftbild)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.04 (22.11.2003):
 | 
				
			||||||
 | 
					- uvcount.pl: Fehler beim Aussortieren von Duplikaten behoben, was
 | 
				
			||||||
 | 
					  i.d.R. nur bei doppelten Mailadressen, nicht aber bei doppelten Namen
 | 
				
			||||||
 | 
					  funktionierte (falsche Regular Expression und Probleme bei
 | 
				
			||||||
 | 
					  unterschiedlicher Gross-/Kleinschreibung der Namen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.03 (19.10.2003):
 | 
				
			||||||
 | 
					- UVsendmail.pm: Vernuenftige Fehlerbehandlung bei SMTP implementiert:
 | 
				
			||||||
 | 
					  Bei fehlgeschlagenen Zustellversuchen wird jetzt die Datei ack.control
 | 
				
			||||||
 | 
					  passend neu geschrieben, so dass mit "uvvote.pl clean" ein neuer
 | 
				
			||||||
 | 
					  Versuch unternommen werden kann. Vorher wurde zwar eine Fehlermeldung
 | 
				
			||||||
 | 
					  angezeigt, die Mail aber einfach geloescht...
 | 
				
			||||||
 | 
					- es wird kein Fehler mehr angezeigt, wenn ack.control bereits existiert,
 | 
				
			||||||
 | 
					  da der Code durchaus damit umgehen kann (es wird einfach an die
 | 
				
			||||||
 | 
					  Datei angehaengt). Entsprechende Fehlermeldung aus messages.txt
 | 
				
			||||||
 | 
					  entfernt
 | 
				
			||||||
 | 
					- Schreibfehler in messages.cfg behoben (ggf. statt ggfls.)
 | 
				
			||||||
 | 
					- me@privacy.net in mailpatterns.cfg aufgenommen
 | 
				
			||||||
 | 
					- UIDLs werden jetzt in der Reihenfolge gespeichert, in der die
 | 
				
			||||||
 | 
					  Mails auf dem POP3-Server lagen. Dadurch ist bei einem Abbruch
 | 
				
			||||||
 | 
					  waehrend der Auswertung leichter kontrollierbar, welche Mails noch
 | 
				
			||||||
 | 
					  einmal abgerufen werden sollen (einfach die letzten X UIDLs aus
 | 
				
			||||||
 | 
					  der Datei uidlcache loeschen)
 | 
				
			||||||
 | 
					- uvcfv.pl, uvbounce.pl und uvvote.pl besitzen jetzt einen Locking-
 | 
				
			||||||
 | 
					  Mechanismus, der ein gleichzeitiges bzw. mehrfaches Starten dieser
 | 
				
			||||||
 | 
					  Programme unterbindet. Andernfalls koennte es zu Inkonsistenzen
 | 
				
			||||||
 | 
					  im Datenbestand kommen (gleichzeitiger Abruf derselben Mailbox,
 | 
				
			||||||
 | 
					  Auswertung noch nicht fertig geschriebener Ergebnisdateien)
 | 
				
			||||||
 | 
					- es koennen jetzt zusaetzliche Konfigurationsdateien in usevote.cfg
 | 
				
			||||||
 | 
					  eingebunden werden, um z.B. die immer gleichen Einstellungen nur
 | 
				
			||||||
 | 
					  einmal zentral abzulegen. Hierzu einfach eine Zeile
 | 
				
			||||||
 | 
					  include dateiname
 | 
				
			||||||
 | 
					  einfuegen. Die Position ist wichtig: Bei mehrfacher Definition
 | 
				
			||||||
 | 
					  der selben Option gilt die letzte. Daher sollte eine globale
 | 
				
			||||||
 | 
					  Konfigurationsdatei am Anfang eingebunden werden, um die
 | 
				
			||||||
 | 
					  Einstellungen bei Bedarf mit wahlspezifischen ueberschreiben zu
 | 
				
			||||||
 | 
					  koennen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.02 (31.05.2003):
 | 
				
			||||||
 | 
					- UVpath.pm wieder entfernt, da mittlerweile eine bessere Loesung
 | 
				
			||||||
 | 
					  gefunden: Das Modul FindBin wird eingesetzt, um den Pfad der
 | 
				
			||||||
 | 
					  ausgefuehrten .pl Datei zu ermitteln. Wenn die .pm Dateien im selben
 | 
				
			||||||
 | 
					  Verzeichnis liegen, werden sie dort gefunden. Ausserdem wurde der
 | 
				
			||||||
 | 
					  Hinweis auf die Umgebungsvariable PERL5LIB in die README Datei
 | 
				
			||||||
 | 
					  aufgenommen, die ansonsten auch auf den Pfad zu den Usevote-Perlmodulen
 | 
				
			||||||
 | 
					  gesetzt werden kann.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.01 (29.05.2003):
 | 
				
			||||||
 | 
					- Wahlschein-, Result- und Bestaetigungsmail-Templates angepasst, so dass
 | 
				
			||||||
 | 
					  bei langem "votename" ein Umbruch im Wahlschein erfolgt und auch bei einer
 | 
				
			||||||
 | 
					  zweistelligen Anzahl von Wahlgegenstaenden eine buendige Ausgabe erfolgt
 | 
				
			||||||
 | 
					- uvballot.pl und Template "result-multi" angepasst, so dass bei
 | 
				
			||||||
 | 
					  Mehrgruppenabstimmungen die Anzahl der Enthaltungen nicht ausgegeben
 | 
				
			||||||
 | 
					  wird (laesst sich nicht als Gesamtzahl ermitteln, koennte man hoechstens
 | 
				
			||||||
 | 
					  fuer jede Gruppe einzeln angeben)
 | 
				
			||||||
 | 
					- Es brauchen jetzt nur noch die Konfigurationsdateien sowie die
 | 
				
			||||||
 | 
					  UVpath.pm in einem Abstimmungsverzeichnis zu liegen, die .pl und .pm
 | 
				
			||||||
 | 
					  Dateien koennen zentral fuer mehrere Abstimmungen abgelegt werden.
 | 
				
			||||||
 | 
					- Formatierungsfunktion "replace" in UVformats.pm implementiert, mit
 | 
				
			||||||
 | 
					  deren Hilfe die Ersetzung von Zeichen oder Zeichenketten in Templates
 | 
				
			||||||
 | 
					  moeglich ist. Praktische Anwendung ist z.B. die Verfremdung von
 | 
				
			||||||
 | 
					  Mailadressen im Result als trivialer Spamschutz. Wie die Templates
 | 
				
			||||||
 | 
					  dafuer geaendert werden muss, ist in der README Datei im Abschnitt 10
 | 
				
			||||||
 | 
					  beschrieben
 | 
				
			||||||
 | 
					- Bei den Standard-Funktionen append und justify (inkl. justify-before
 | 
				
			||||||
 | 
					  und justify-behind) wird der uebergebene Key jetzt rekursiv ueber die
 | 
				
			||||||
 | 
					  Formatdefinitionen im Template aufgeloest. Das ermoeglicht die
 | 
				
			||||||
 | 
					  Vorbehandlung eines Wertes, z.B.:
 | 
				
			||||||
 | 
					    mail := value mail | replace '@' '-at-'
 | 
				
			||||||
 | 
					    line := value name | justify-before mail 70
 | 
				
			||||||
 | 
					  Hier wurde vorher die unveraenderte Mailadresse benutzt, jetzt wird
 | 
				
			||||||
 | 
					  die obere Definition beachtet und zunaechst die Ersetzung durchgefuehrt.
 | 
				
			||||||
 | 
					- Formatierungsfunktion "sprintf" in UVformats.pm implementiert, um
 | 
				
			||||||
 | 
					  z.B. Verhaeltnisse in Results formatiert ausgeben zu koennen
 | 
				
			||||||
 | 
					- Auswertung nach Verhaeltnis Ja- zu Nein-Stimmen implementiert
 | 
				
			||||||
 | 
					  (in usevote.cfg proportional=1 setzen und prop_formula passend waehlen).
 | 
				
			||||||
 | 
					  Damit ist z.B. fuer jeden Abstimmungsgegenstand das Verhaeltnis oder
 | 
				
			||||||
 | 
					  auch die Differenz zwischen Ja- und Nein-Stimmen ermittelbar. Letzteres
 | 
				
			||||||
 | 
					  wird fuer Moderationsnachwahlen benoetigt. Kombiniert werden kann dies
 | 
				
			||||||
 | 
					  mit einer weiteren Bedingung, z.B. mindestens soviele Ja- wie Nein-Stimmen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0 (22.03.2003):
 | 
				
			||||||
 | 
					- UVformats.pm dokumentiert
 | 
				
			||||||
 | 
					- Defaultwert fuer "formats" korrigiert (UVconfig.pm)
 | 
				
			||||||
 | 
					- Defaultwert fuer "bdsgfile" fehlte (UVconfig.pm)
 | 
				
			||||||
 | 
					- kosmetische Aenderung (fehlende Leerzeichen) an Template result-multi
 | 
				
			||||||
 | 
					- Windows-Pager-Empfehlung in README und usevote.cfg geaendert (vorher
 | 
				
			||||||
 | 
					  wurde "more" empfohlen, da mitgeliefert, aber more ist so buggy, dass
 | 
				
			||||||
 | 
					  jetzt die Installation von "less" nahegelegt wird
 | 
				
			||||||
 | 
					- Fehler in UVsendmail.pm behoben: Wenn beim "uvvote.pl clean" Aufruf keine
 | 
				
			||||||
 | 
					  Mails zu verschicken waren, wurde das Programm in UVsendmail::send()
 | 
				
			||||||
 | 
					  einfach mit "exit 0" beendet (korrigiert in "return 0"). Ausserdem
 | 
				
			||||||
 | 
					  wurde die Fehlermeldung wegen eines Schreibfehlers im Konstantennamen
 | 
				
			||||||
 | 
					  nicht angezeigt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta15:
 | 
				
			||||||
 | 
					- Fehlermeldung bei nicht vorhandener messages.cfg korrigiert
 | 
				
			||||||
 | 
					  (Dateiname wurde wegen falschen Configschluessels nicht angezeigt)
 | 
				
			||||||
 | 
					- Bei manuell eingegebener Scheinkennung wurde irrtuemlicherweise eine
 | 
				
			||||||
 | 
					  Fehlermeldung angezeigt, auch wenn die Kennung zur Mailadresse passte
 | 
				
			||||||
 | 
					- Bei neu eingegebener Mailadresse wurde die Zugehoerigkeit der
 | 
				
			||||||
 | 
					  Scheinkennung nicht neu geprueft
 | 
				
			||||||
 | 
					- bei nicht erkannten Abstimmungspunkten im Wahlschein wurde eine
 | 
				
			||||||
 | 
					  Warnmeldung angezeigt, die auf Nicht-Wertung hinwies. In Wirklichkeit
 | 
				
			||||||
 | 
					  wurde die Stimme aber normal bestaetigt und lediglich alle nicht erkannten
 | 
				
			||||||
 | 
					  Punkte als "Enthaltung" gewertet. Die Warnmeldung erscheint jetzt nicht
 | 
				
			||||||
 | 
					  mehr, um keine Verwirrung zu stiften.
 | 
				
			||||||
 | 
					- Fehler in UVmessage.pm behoben: Der Wert 0 wurde durch den leeren String
 | 
				
			||||||
 | 
					  ersetzt. Jetzt wird defined() eingesetzt statt auf true/false zu pruefen.
 | 
				
			||||||
 | 
					- Fehler in UVsendmail.pm behoben: Wenn kein SMTP aktiviert war, wurde
 | 
				
			||||||
 | 
					  die "domail" Datei mit den MTA-Aufrufen zwar geschrieben, aber nicht
 | 
				
			||||||
 | 
					  ausgefuehrt. Dadurch schlug auch das Loeschen der Temp-Dateien fehl,
 | 
				
			||||||
 | 
					  was beim naechsten Aufruf Fehlermeldungen verursachte.
 | 
				
			||||||
 | 
					- Templates eingebaut
 | 
				
			||||||
 | 
					- acktext.txt durch Templates ersetzt. BDSG-Text ist jetzt in der
 | 
				
			||||||
 | 
					  Datei bdsgtext.cfg
 | 
				
			||||||
 | 
					- "cfvfile" Option entfernt (nicht mehr noetig, durch Templates abgeloest)
 | 
				
			||||||
 | 
					- Bedingungen fuer Wahlerfolg ueber usevote.cfg konfigurierbar gemacht.
 | 
				
			||||||
 | 
					  Standardwerte:
 | 
				
			||||||
 | 
					  condition1 = $yes>=2*$no
 | 
				
			||||||
 | 
					  condition2 = $yes>=60
 | 
				
			||||||
 | 
					- usevote.cfg bzgl. der Ueberschriften "jedes Mal anpassen" / "nur einmal
 | 
				
			||||||
 | 
					  anpassen" ein wenig umsortiert
 | 
				
			||||||
 | 
					- wenn kein "smtphelo" definiert wurde, wird jetzt der eigene
 | 
				
			||||||
 | 
					  Hostname genommen
 | 
				
			||||||
 | 
					- README an aktuelle Aenderungen angepasst (Dateilisten, Beschreibungen
 | 
				
			||||||
 | 
					  der Menues) und vervollstaendigt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta14:
 | 
				
			||||||
 | 
					- Fehler in UVmenu.pm behoben, der beim Auswaehlen von
 | 
				
			||||||
 | 
					  "Stimmen vom Waehler annulliert" im Menue auftrat
 | 
				
			||||||
 | 
					- Erkennung von doppelten, sich widersprechenden Stimmabgaben in einer
 | 
				
			||||||
 | 
					  Mail funktioniert jetzt
 | 
				
			||||||
 | 
					- beim Verschicken per SMTP gibt es die neue Option envelopefrom, die
 | 
				
			||||||
 | 
					  die Absenderadresse im Envelope (Return-Path) enthaelt, an die auch
 | 
				
			||||||
 | 
					  Bounces zurueckgehen
 | 
				
			||||||
 | 
					- Neu: Erkennung von fehlenden Abstimmungspunkten im Wahlschein, Behandlung
 | 
				
			||||||
 | 
					  wie bei unleserlichen Stimmabgaben mit entsprechendem Hinweis im Menue
 | 
				
			||||||
 | 
					- Fehler in uvvote.pl behoben, der bei unleserlichen Stimmabgaben auftrat
 | 
				
			||||||
 | 
					- statt encode_mimewords wird jetzt encode_mimeword verwendet und das
 | 
				
			||||||
 | 
					  "Drumherum" komplett selbst gemacht. Man schaue in den Code von
 | 
				
			||||||
 | 
					  MIME::Words::encode_mimewords(), dann weiss man, warum ;-)
 | 
				
			||||||
 | 
					- Weitere Texte in messages.txt ausgelagert (uvvote.pl, uvcount.pl)
 | 
				
			||||||
 | 
					- config test (-t Option) gibt jetzt auch Auskunft ueber die Konfiguration
 | 
				
			||||||
 | 
					  (falls Option nicht in usevote.cfg gesetzt, wird der Standardwert
 | 
				
			||||||
 | 
					  ausgegeben)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta13:
 | 
				
			||||||
 | 
					- Fehlerbehandlung bei SMTP eingefuehrt, so dass keine Mails verloren gehen
 | 
				
			||||||
 | 
					- es laesst sich jetzt ein anderer Port fuer SMTP/POP3 angeben
 | 
				
			||||||
 | 
					- uvbounce.pl benutzt jetzt auch POP3, falls dieses in usevote.cfg aktiviert
 | 
				
			||||||
 | 
					  wurde. Mit der Option -f ist aber unabhaengig davon das Einlesen der
 | 
				
			||||||
 | 
					  Bounces aus einer Datei in jedem Fall moeglich
 | 
				
			||||||
 | 
					- auftretende Fehler beim Ausfuehren von uvvote.pl werden jetzt in eine
 | 
				
			||||||
 | 
					  Datei geschrieben und beim Verlassen wird darauf hingewiesen
 | 
				
			||||||
 | 
					- Wenn das interaktive Menue ausgeblendet und dazu der Bildschirm geloescht
 | 
				
			||||||
 | 
					  wird, informiert jetzt eine Meldung darueber, dass Mails verarbeitet werden
 | 
				
			||||||
 | 
					- Menues so umgestellt, dass [a] immer fuer "alles OK" steht, egal ob
 | 
				
			||||||
 | 
					  Mailadresse, Name, Stimmen oder die BDSG-Klausel strittig sind
 | 
				
			||||||
 | 
					- Ausgaben/Texte von UVreadmail.pm und UVsendmail.pm nach messages.txt
 | 
				
			||||||
 | 
					  ausgelagert
 | 
				
			||||||
 | 
					- Verzeichnisnamen "fertig" und "tmp" jetzt konfigurierbar
 | 
				
			||||||
 | 
					- Zeilen "Waehleradresse: " und "Wahlscheinkennung: " im Wahlschein
 | 
				
			||||||
 | 
					  konfigurierbar gemacht
 | 
				
			||||||
 | 
					- Pager konfigurierbar gemacht (vorher immer "more") und standardmaessig
 | 
				
			||||||
 | 
					  auf "less" gesetzt, weil "more" mit der Umleitung von STDERR Probleme hat
 | 
				
			||||||
 | 
					- kleinere Bugs behoben
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta12:
 | 
				
			||||||
 | 
					- Fehler in Menue behoben
 | 
				
			||||||
 | 
					- im Menue kann man jetzt explizit Stimmen ungueltig werten, indem man
 | 
				
			||||||
 | 
					  den Namen, die Adresse oder die Stimmen ungueltig macht. Es wird eine
 | 
				
			||||||
 | 
					  passende Fehlermail generiert.
 | 
				
			||||||
 | 
					- genauso kann man jetzt explizit annullieren (sinnvoll, falls der Waehler
 | 
				
			||||||
 | 
					  z.B. "annullierung" falsch buchstabiert hat *g*), wobei automatisch
 | 
				
			||||||
 | 
					  diverse andere Probleme als irrelevant erkannt werden (z.B. braucht man
 | 
				
			||||||
 | 
					  in dem Fall keinen Datenschutzhinweis zu akzeptieren und nicht unbedingt
 | 
				
			||||||
 | 
					  einen Namen anzugeben, falls die Adresse stimmt)
 | 
				
			||||||
 | 
					- MIME-Kodierung fuer Subject- und From-Header in UVsendmail.pm eingefuehrt
 | 
				
			||||||
 | 
					- In Bestaetigungsmails gibt es jetzt kein gesondertes Feld mehr zum
 | 
				
			||||||
 | 
					  Korrigieren des Namens, sondern es kann einfach die ohnehin vorhandene
 | 
				
			||||||
 | 
					  Zeile "Wahlername: Vorname Nachname" editiert werden.
 | 
				
			||||||
 | 
					- "nametext2" in usevote.cfg ist jetzt "Waehlername:" und wird auch
 | 
				
			||||||
 | 
					  statt des fest kodierten Strings an den entsprechenden Codestellen
 | 
				
			||||||
 | 
					  verwendet
 | 
				
			||||||
 | 
					- uvcount.pl: Bugs bei Annullierungen und fehlendem Namen behoben
 | 
				
			||||||
 | 
					- uvbounce an geaendertes UVreadmail.pm angepasst (funktioniert bei
 | 
				
			||||||
 | 
					  Aktivierung des POP3-Zugriffs nicht mehr)
 | 
				
			||||||
 | 
					- saemtliche Ausgaben/Texte in UVmenu.pm nach messages.txt ausgelagert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta11:
 | 
				
			||||||
 | 
					- kompletter Rewrite der Ueberpruefungsfunktionen in uvvote.pl und UVmenu.pl.
 | 
				
			||||||
 | 
					  Es werden jetzt alle Fehler an ein Array angehaengt und in einem Rutsch
 | 
				
			||||||
 | 
					  von der Menue-Funktion verarbeitet. Fuer Darstellung der Votemail wird
 | 
				
			||||||
 | 
					  "more" benutzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta10:
 | 
				
			||||||
 | 
					- Zeilenumbrueche richten sich jetzt nach der "rightmargin"-Einstellung
 | 
				
			||||||
 | 
					  aus usevote.cfg (vorher waren die Zeilenlaengen teilweise noch hartkodiert)
 | 
				
			||||||
 | 
					- Fehler beim Erstellen des domail-Scripts behoben
 | 
				
			||||||
 | 
					- kosmetische Code-Aenderungen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta9:
 | 
				
			||||||
 | 
					- Auch bei zurueckgeschickten (korrigierten) Wahlbestaetigungen wird
 | 
				
			||||||
 | 
					  jetzt der Name automatisch im Body erkannt (Zeile "Waehlername:").
 | 
				
			||||||
 | 
					- Regular Expressions zur Stimmerkennung geaendert: Manche komische
 | 
				
			||||||
 | 
					  Mailprogramme benutzen zum Kodieren von Leerzeichen =A0, was aber
 | 
				
			||||||
 | 
					  nach der Dekodierung nicht als \s erkannt wird. \W ist nicht optimal,
 | 
				
			||||||
 | 
					  aber funktioniert.
 | 
				
			||||||
 | 
					- uvbounce.pl: Bounces von Antworten auf Wahlscheinanforderungen werden
 | 
				
			||||||
 | 
					  jetzt erkannt und mit einem gesonderten Hinweis gekennzeichnet
 | 
				
			||||||
 | 
					  ("Wahlschein nicht zustellbar")
 | 
				
			||||||
 | 
					- in den Config Files koennen die Kommentarzeichen escaped werden: \#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta8:
 | 
				
			||||||
 | 
					- beim Einlesen aus usevote.cfg wird ein eventuelles \r geloescht
 | 
				
			||||||
 | 
					- es werden nicht mehr jedes Mal saemtliche Mails abgerufen (bei POP3),
 | 
				
			||||||
 | 
					  sondern es wird mit dem UIDL Kommando geprueft, ob schon ein vorheriger
 | 
				
			||||||
 | 
					  Abruf stattfand. Ausserdem ist es jetzt moeglich, die Mails vom Server
 | 
				
			||||||
 | 
					  zu loeschen.
 | 
				
			||||||
 | 
					- uvcfv.pl kann jetzt auch richtig mit POP3 umgehen
 | 
				
			||||||
 | 
					- Platzhalter im Wahlschein bei personalisierten Wahlscheinen geaendert
 | 
				
			||||||
 | 
					- Aktuelle Werte werden teilweise jetzt im Menue angezeigt (wenn man
 | 
				
			||||||
 | 
					  Stimmen, Name oder Mailadresse neu gesetzt hat)
 | 
				
			||||||
 | 
					- Dokumentation verbessert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta7:
 | 
				
			||||||
 | 
					- kosmetische Code-Aenderungen (Vereinfachungen, Verschoenerungen, ...)
 | 
				
			||||||
 | 
					- Inhalt der Datei bdsgtext.txt als Abschnitt [BDSG Hinweis] in
 | 
				
			||||||
 | 
					  acktext.txt uebernommen (es gibt keinen Grund dafuer, dass dieser
 | 
				
			||||||
 | 
					  Text eine eigene Datei bekommen sollte...)
 | 
				
			||||||
 | 
					- Testweise einige Programm-Meldungen in externe Datei (meldungen.cfg)
 | 
				
			||||||
 | 
					  ausgelagert, um eine leichtere Anpassung zu ermoeglichen (z.B.
 | 
				
			||||||
 | 
					  Uebersetzung in andere Sprachen). Nach und nach werden saemtliche
 | 
				
			||||||
 | 
					  Meldungen in diese Konfigurationsdatei wandern.
 | 
				
			||||||
 | 
					- acktext.txt in acktext.cfg umbenannt: Alle Konfigurationsdateien
 | 
				
			||||||
 | 
					  haben damit die Endung .cfg
 | 
				
			||||||
 | 
					- POP3-Abruf und Verschicken per SMTP eingebaut
 | 
				
			||||||
 | 
					- Shellbefehl-Aufrufe (chmod- und mkdir) durch Perl-Pendants ersetzt,
 | 
				
			||||||
 | 
					  um Plattformunabhaengigkeit zu bieten
 | 
				
			||||||
 | 
					- In uvcfv.pl Doppelung im Mailsubject geloescht
 | 
				
			||||||
 | 
					- In uvcount.pl stimmte die Zuordnung von Abstimmungsgegenstand zur
 | 
				
			||||||
 | 
					  einzelnen Stimmabgabe nicht (umgekehrte Reihenfolge)
 | 
				
			||||||
 | 
					- in UVmenu.pm entstand bei Mehrgruppenabstimmungen der Kommentar
 | 
				
			||||||
 | 
					  "Wahlleiter setzte Stimmen, Stimmen, Stimmen" (jetzt nur noch
 | 
				
			||||||
 | 
					  einmal gesetzt statt fuer jede Gruppe)
 | 
				
			||||||
 | 
					- Falls keine Scheinkennung und keine BDSG-Zustimmung: Bislang wurden
 | 
				
			||||||
 | 
					  dann zwei Mails generiert (keine Abfrage auf bereits aufgetretenen
 | 
				
			||||||
 | 
					  Fehler), nun behoben
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta6:
 | 
				
			||||||
 | 
					- RegExp fuer Namensangabe im Body verbessert (wenn kein Name angegeben
 | 
				
			||||||
 | 
					  wurde und auch im Header keiner zu finden war, wurde der nachfolgende
 | 
				
			||||||
 | 
					  Hinweissatz "Wenn Du keinen Namen angibst..." als Realname erkannt
 | 
				
			||||||
 | 
					- RegExp fuer Namenserkennung konfigurierbar gemacht (usevote.cfg)
 | 
				
			||||||
 | 
					  und um Accents erweitert
 | 
				
			||||||
 | 
					- RegExp fuer Erkennung verdaechtiger Adressen trifft jetzt nur noch
 | 
				
			||||||
 | 
					  zu, wenn der String direkt am Anfang der Adresse steht. Gegenteiliges
 | 
				
			||||||
 | 
					  Verhalten kann durch Wildcards herbeigefuehrt werden
 | 
				
			||||||
 | 
					- Statt manuellen Trennens von Header und Body wird in UVreadmail.pm
 | 
				
			||||||
 | 
					  jetzt das Modul MIME::Parser eingesetzt
 | 
				
			||||||
 | 
					- kleinere Bugs behoben (z.B. einfache vs. doppelte Anfuehrungsstriche)
 | 
				
			||||||
 | 
					- Fehler bei UVmenu::menu-Aufruf im Falle von "keine Stimmen" behoben
 | 
				
			||||||
 | 
					  (eine Variable fehlte in der Uebergabeliste)
 | 
				
			||||||
 | 
					- uvcount.pl um Eingruppen-Format ergaenzt
 | 
				
			||||||
 | 
					- uvballot.pl um Option -t ergaenzt, um eine Vorlage fuer cfv.txt bei
 | 
				
			||||||
 | 
					  Verwendung von personalisierten Wahlscheinen zu erzeugen
 | 
				
			||||||
 | 
					- uvbounce.pl zur Generierung von ungueltigen Adressen aus einer
 | 
				
			||||||
 | 
					  Mailbox mit Bounces implementiert
 | 
				
			||||||
 | 
					- Bei Annullierungen wird jetzt nicht mehr die BDSG-Klausel geprueft
 | 
				
			||||||
 | 
					  (es erfolgt ja ohnehin eine Loeschung der Stimmabgabe)
 | 
				
			||||||
 | 
					- Statt Mail::Field wird nun eine eigene RegExp verwendet (Danke an
 | 
				
			||||||
 | 
					  Marc Brockschmidt fuer die Idee), Mail::Field hat einige unschoene Bugs.
 | 
				
			||||||
 | 
					- Bei nicht erkannten Stimmabgaben bei Abstimmungen mit nur einem
 | 
				
			||||||
 | 
					  Abstimmungsgegenstand wird nun auch die Ungueltigwertung angeboten
 | 
				
			||||||
 | 
					  (als Alternative zu "Enthaltung").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta5:
 | 
				
			||||||
 | 
					- die Mailboxdatei wird nun vor der Verarbeitung verschoben, so dass waehrend
 | 
				
			||||||
 | 
					  des uvvote-Laufs keine neuen Mails angehaengt werden koennen
 | 
				
			||||||
 | 
					- es wird jetzt fuer jeden Durchlauf eine gesonderte Ergebnisdatei angelegt
 | 
				
			||||||
 | 
					- neu eingefuehrter Parameter "clean", der Bestaetigungen verschickt,
 | 
				
			||||||
 | 
					  Ergebnisdatei und die Mailbox in das Verzeichnis fertig/ verschiebt,
 | 
				
			||||||
 | 
					  temporaere Dateien loescht und aus allen Einzelergebnissen eine neue
 | 
				
			||||||
 | 
					  Gesamtergebnisdatei (normalerweise "ergebnis.alle") erstellt
 | 
				
			||||||
 | 
					- dadurch sind jetzt zwei Durchgaenge erforderlich: Erster Aufruf ohne
 | 
				
			||||||
 | 
					  die Option "clean" (Erzeugt die Ergebnisse und Mailvorlagen), dann kann
 | 
				
			||||||
 | 
					  eine Kontrolle erfolgen, anschliessend ein weiterer Aufruf mit der Option
 | 
				
			||||||
 | 
					  "clean" zum Aufraeumen und Verschicken der Bestaetigungen
 | 
				
			||||||
 | 
					- neues Modul UVsendmail.pm, in das die Funktion zum Erstellen von
 | 
				
			||||||
 | 
					  Mails ausgelagert wurde
 | 
				
			||||||
 | 
					- neues Modul UVmenu.pm mit der Menuefunktionalitaet zum interaktiven
 | 
				
			||||||
 | 
					  Eingriff in die Stimmwertung
 | 
				
			||||||
 | 
					- Bugs bei Stimmaufzeichnung behoben: Fehlerhafte Stimmen wurden teilweise
 | 
				
			||||||
 | 
					  nicht in der Ergebnisdatei vermerkt. Ausserdem wurde nicht konsequent
 | 
				
			||||||
 | 
					  auf die Option "voteack" geprueft
 | 
				
			||||||
 | 
					- Reply-To kann jetzt beachtet werden (muss in usevote.cfg eingeschaltet
 | 
				
			||||||
 | 
					  werden) und ueberschreibt das From. Mit Vorsicht zu geniessen, da so
 | 
				
			||||||
 | 
					  jeder Waehler fuer andere Stimmen abgeben und die Bestaetigungen zu
 | 
				
			||||||
 | 
					  sich umlenken kann!
 | 
				
			||||||
 | 
					- Umgang mit personalisierten Wahlscheinen (Abschnitt 6a der Wahlregeln
 | 
				
			||||||
 | 
					  fuer de.*), Generierung und Pruefung von Scheinkennungen. Siehe Optionen
 | 
				
			||||||
 | 
					  "personal" und "idfile" in usevote.cfg sowie das Programm uvcfv.pl zum
 | 
				
			||||||
 | 
					  Verschicken der persoenlichen Wahlscheine
 | 
				
			||||||
 | 
					- Das Flag beim Aufruf der Menuefunktion ist jetzt ein Hash, in dem
 | 
				
			||||||
 | 
					  diverse Werte ueber- und zurueckgegeben werden. Dadurch auch feine
 | 
				
			||||||
 | 
					  Steuerung der aktiven Menuepunkte moeglich
 | 
				
			||||||
 | 
					- Ausgabe der Fehlermeldung in UVmenu.pm verlagert (wird in besagtem
 | 
				
			||||||
 | 
					  Hash uebergeben)
 | 
				
			||||||
 | 
					- Kommentarfeld fuer Ergebisdatei ("Wahlleiter setzte xyz") wird erst
 | 
				
			||||||
 | 
					  zum Schluss erzeugt, vorher werden nur die vom Wahlleiter manuell
 | 
				
			||||||
 | 
					  veraenderten Felder in einem Array mitgefuehrt
 | 
				
			||||||
 | 
					- uvcfv.pl zum Generieren der persoenlichen Wahlscheine und Verschicken
 | 
				
			||||||
 | 
					  des CfVs implementiert
 | 
				
			||||||
 | 
					- Bisherige Funktionalitaet von uvack, uvcount, uvdup in uvcount.pl
 | 
				
			||||||
 | 
					  implementiert
 | 
				
			||||||
 | 
					- uvballot.pl zum Erstellen eines Musterwahlscheins
 | 
				
			||||||
 | 
					- uvcfv.pl: Es wird nun auch die Vollstaendigkeit von $config{bdsgtext}
 | 
				
			||||||
 | 
					  im Wahlschein geprueft und bei Auswahl von "Ende+Speichern" wird
 | 
				
			||||||
 | 
					  noch einmal zur Sicherheit gefragt, ob die Stimme wirklich
 | 
				
			||||||
 | 
					  gespeichert und verarbeitet werden soll
 | 
				
			||||||
 | 
					- Kompatibilitaetsprobleme mit Perl 5.6.1 bei Variablenzuweisungen behoben
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta4:
 | 
				
			||||||
 | 
					- bei Regelverletzung wird jetzt ein interaktives Menue aufgerufen,
 | 
				
			||||||
 | 
					  so dass der Wahlleiter entscheiden kann, was er machen will
 | 
				
			||||||
 | 
					- Stimmerkennung legt unbekannte Vote-Strings (nicht Ja, Nein,
 | 
				
			||||||
 | 
					  Enthaltung oder Annullierung) jetzt dem Wahlleiter vor und
 | 
				
			||||||
 | 
					  laesst ihn entscheiden (Default ist Enthaltung). Fehlermail ist
 | 
				
			||||||
 | 
					  in so einem Fall bislang nicht vorgesehen, laesst sich aber noch
 | 
				
			||||||
 | 
					  einbauen, falls erforderlich. Wenn der Waehler die Bestaetigung
 | 
				
			||||||
 | 
					  ueberprueft, reicht es auch, wenn dort "Enthaltung" auftaucht...
 | 
				
			||||||
 | 
					- Pruefung auf vollstaendige Bestaetigung der Datenschutz-Klausel
 | 
				
			||||||
 | 
					  ist implementiert und ueber usevote.cfg und bdsgtext.txt konfigurierbar
 | 
				
			||||||
 | 
					- Regelpruefung kompakter und dreimal schneller gemacht (Idee von
 | 
				
			||||||
 | 
					  Cornell Binder), dafuer Code schlechter lesbar... aber dokumentiert ;-)
 | 
				
			||||||
 | 
					- Alle Regel-Subs in UVrules.pm ausgelagert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta3:
 | 
				
			||||||
 | 
					- Einlesen und Testen der Konfiguration sowie Ausgabe der Regeln
 | 
				
			||||||
 | 
					  im Klartext sind jetzt im externen Modul UsevoteConfig.pm untergebracht
 | 
				
			||||||
 | 
					- Das Einlesen der Mail und MIME-Bearbeitung erfolgt wurde in das
 | 
				
			||||||
 | 
					  Modul UsevoteReadmail.pm ausgelagert
 | 
				
			||||||
 | 
					- verdaechtige Mailadressen werden nun in einer gesonderten Datei
 | 
				
			||||||
 | 
					  konfiguriert (Default: mailpatterns.cfg)
 | 
				
			||||||
 | 
					- Fehler bei Parsing von %body% und %headbody% in acktext.txt behoben
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta2:
 | 
				
			||||||
 | 
					- Auslagerung des Abschnittes [Realname Info] nach acktext.txt
 | 
				
			||||||
 | 
					  (vorher hardcoded)
 | 
				
			||||||
 | 
					- Einfuehrung des Platzhalters %version% fuer acktext.txt
 | 
				
			||||||
 | 
					- Einfuehrung der Option voteack (Einzelbestaetigung kann deaktiviert werden)
 | 
				
			||||||
 | 
					- saemtliche Konfigurationsoptionen sind nun mit Defaultwerten belegt,
 | 
				
			||||||
 | 
					  aber wahlspezifische Optionen (Gruppennamen etc.) muessen natuerlich
 | 
				
			||||||
 | 
					  auf jeden Fall gesetzt werden
 | 
				
			||||||
 | 
					- Aenderung der Stimmerkennungsmethode. Um problemlos mit eigenwilligen
 | 
				
			||||||
 | 
					  Zeilenumbruechen diverser schrottiger Software umgehen zu koennen,
 | 
				
			||||||
 | 
					  wird ein Identifier an den Zeilenanfang gesetzt und direkt dahinter
 | 
				
			||||||
 | 
					  die Stimme. Der Gruppenname kann dann ruhig umgebrochen sein.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version 4.0beta1:
 | 
				
			||||||
 | 
					- kompletter Rewrite in Perl. Noch ziemlich unvollstaendig (nur uvvote.pl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bis Version 3.1beta7 (Wolfgang Behrens):
 | 
				
			||||||
 | 
					- Funktionialitaet fuer persoenliche Wahlschein eingebaut
 | 
				
			||||||
 | 
					- Reply-To Auswertung u.a. auf GVV-Beduerfnisse angepasst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version Usevote 3.0a
 | 
				
			||||||
 | 
					- Uebersetzung ins Deutsche und Anpassung an Wahlregeln in de.*
 | 
				
			||||||
 | 
					  (Frederik Ramm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version Usevote 3.0
 | 
				
			||||||
 | 
					- Urversion von Ron Dippold (Englisch), nicht an hiesige Wahlregeln angepasst
 | 
				
			||||||
							
								
								
									
										339
									
								
								COPYING
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								COPYING
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,339 @@
 | 
				
			||||||
 | 
							    GNU GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
							       Version 2, June 1991
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 | 
				
			||||||
 | 
					                          675 Mass Ave, Cambridge, MA 02139, USA
 | 
				
			||||||
 | 
					 Everyone is permitted to copy and distribute verbatim copies
 | 
				
			||||||
 | 
					 of this license document, but changing it is not allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								    Preamble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The licenses for most software are designed to take away your
 | 
				
			||||||
 | 
					freedom to share and change it.  By contrast, the GNU General Public
 | 
				
			||||||
 | 
					License is intended to guarantee your freedom to share and change free
 | 
				
			||||||
 | 
					software--to make sure the software is free for all its users.  This
 | 
				
			||||||
 | 
					General Public License applies to most of the Free Software
 | 
				
			||||||
 | 
					Foundation's software and to any other program whose authors commit to
 | 
				
			||||||
 | 
					using it.  (Some other Free Software Foundation software is covered by
 | 
				
			||||||
 | 
					the GNU Library General Public License instead.)  You can apply it to
 | 
				
			||||||
 | 
					your programs, too.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  When we speak of free software, we are referring to freedom, not
 | 
				
			||||||
 | 
					price.  Our General Public Licenses are designed to make sure that you
 | 
				
			||||||
 | 
					have the freedom to distribute copies of free software (and charge for
 | 
				
			||||||
 | 
					this service if you wish), that you receive source code or can get it
 | 
				
			||||||
 | 
					if you want it, that you can change the software or use pieces of it
 | 
				
			||||||
 | 
					in new free programs; and that you know you can do these things.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To protect your rights, we need to make restrictions that forbid
 | 
				
			||||||
 | 
					anyone to deny you these rights or to ask you to surrender the rights.
 | 
				
			||||||
 | 
					These restrictions translate to certain responsibilities for you if you
 | 
				
			||||||
 | 
					distribute copies of the software, or if you modify it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  For example, if you distribute copies of such a program, whether
 | 
				
			||||||
 | 
					gratis or for a fee, you must give the recipients all the rights that
 | 
				
			||||||
 | 
					you have.  You must make sure that they, too, receive or can get the
 | 
				
			||||||
 | 
					source code.  And you must show them these terms so they know their
 | 
				
			||||||
 | 
					rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  We protect your rights with two steps: (1) copyright the software, and
 | 
				
			||||||
 | 
					(2) offer you this license which gives you legal permission to copy,
 | 
				
			||||||
 | 
					distribute and/or modify the software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Also, for each author's protection and ours, we want to make certain
 | 
				
			||||||
 | 
					that everyone understands that there is no warranty for this free
 | 
				
			||||||
 | 
					software.  If the software is modified by someone else and passed on, we
 | 
				
			||||||
 | 
					want its recipients to know that what they have is not the original, so
 | 
				
			||||||
 | 
					that any problems introduced by others will not reflect on the original
 | 
				
			||||||
 | 
					authors' reputations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Finally, any free program is threatened constantly by software
 | 
				
			||||||
 | 
					patents.  We wish to avoid the danger that redistributors of a free
 | 
				
			||||||
 | 
					program will individually obtain patent licenses, in effect making the
 | 
				
			||||||
 | 
					program proprietary.  To prevent this, we have made it clear that any
 | 
				
			||||||
 | 
					patent must be licensed for everyone's free use or not licensed at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The precise terms and conditions for copying, distribution and
 | 
				
			||||||
 | 
					modification follow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							    GNU GENERAL PUBLIC LICENSE
 | 
				
			||||||
 | 
					   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  0. This License applies to any program or other work which contains
 | 
				
			||||||
 | 
					a notice placed by the copyright holder saying it may be distributed
 | 
				
			||||||
 | 
					under the terms of this General Public License.  The "Program", below,
 | 
				
			||||||
 | 
					refers to any such program or work, and a "work based on the Program"
 | 
				
			||||||
 | 
					means either the Program or any derivative work under copyright law:
 | 
				
			||||||
 | 
					that is to say, a work containing the Program or a portion of it,
 | 
				
			||||||
 | 
					either verbatim or with modifications and/or translated into another
 | 
				
			||||||
 | 
					language.  (Hereinafter, translation is included without limitation in
 | 
				
			||||||
 | 
					the term "modification".)  Each licensee is addressed as "you".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Activities other than copying, distribution and modification are not
 | 
				
			||||||
 | 
					covered by this License; they are outside its scope.  The act of
 | 
				
			||||||
 | 
					running the Program is not restricted, and the output from the Program
 | 
				
			||||||
 | 
					is covered only if its contents constitute a work based on the
 | 
				
			||||||
 | 
					Program (independent of having been made by running the Program).
 | 
				
			||||||
 | 
					Whether that is true depends on what the Program does.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. You may copy and distribute verbatim copies of the Program's
 | 
				
			||||||
 | 
					source code as you receive it, in any medium, provided that you
 | 
				
			||||||
 | 
					conspicuously and appropriately publish on each copy an appropriate
 | 
				
			||||||
 | 
					copyright notice and disclaimer of warranty; keep intact all the
 | 
				
			||||||
 | 
					notices that refer to this License and to the absence of any warranty;
 | 
				
			||||||
 | 
					and give any other recipients of the Program a copy of this License
 | 
				
			||||||
 | 
					along with the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may charge a fee for the physical act of transferring a copy, and
 | 
				
			||||||
 | 
					you may at your option offer warranty protection in exchange for a fee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  2. You may modify your copy or copies of the Program or any portion
 | 
				
			||||||
 | 
					of it, thus forming a work based on the Program, and copy and
 | 
				
			||||||
 | 
					distribute such modifications or work under the terms of Section 1
 | 
				
			||||||
 | 
					above, provided that you also meet all of these conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) You must cause the modified files to carry prominent notices
 | 
				
			||||||
 | 
					    stating that you changed the files and the date of any change.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) You must cause any work that you distribute or publish, that in
 | 
				
			||||||
 | 
					    whole or in part contains or is derived from the Program or any
 | 
				
			||||||
 | 
					    part thereof, to be licensed as a whole at no charge to all third
 | 
				
			||||||
 | 
					    parties under the terms of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) If the modified program normally reads commands interactively
 | 
				
			||||||
 | 
					    when run, you must cause it, when started running for such
 | 
				
			||||||
 | 
					    interactive use in the most ordinary way, to print or display an
 | 
				
			||||||
 | 
					    announcement including an appropriate copyright notice and a
 | 
				
			||||||
 | 
					    notice that there is no warranty (or else, saying that you provide
 | 
				
			||||||
 | 
					    a warranty) and that users may redistribute the program under
 | 
				
			||||||
 | 
					    these conditions, and telling the user how to view a copy of this
 | 
				
			||||||
 | 
					    License.  (Exception: if the Program itself is interactive but
 | 
				
			||||||
 | 
					    does not normally print such an announcement, your work based on
 | 
				
			||||||
 | 
					    the Program is not required to print an announcement.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These requirements apply to the modified work as a whole.  If
 | 
				
			||||||
 | 
					identifiable sections of that work are not derived from the Program,
 | 
				
			||||||
 | 
					and can be reasonably considered independent and separate works in
 | 
				
			||||||
 | 
					themselves, then this License, and its terms, do not apply to those
 | 
				
			||||||
 | 
					sections when you distribute them as separate works.  But when you
 | 
				
			||||||
 | 
					distribute the same sections as part of a whole which is a work based
 | 
				
			||||||
 | 
					on the Program, the distribution of the whole must be on the terms of
 | 
				
			||||||
 | 
					this License, whose permissions for other licensees extend to the
 | 
				
			||||||
 | 
					entire whole, and thus to each and every part regardless of who wrote it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thus, it is not the intent of this section to claim rights or contest
 | 
				
			||||||
 | 
					your rights to work written entirely by you; rather, the intent is to
 | 
				
			||||||
 | 
					exercise the right to control the distribution of derivative or
 | 
				
			||||||
 | 
					collective works based on the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition, mere aggregation of another work not based on the Program
 | 
				
			||||||
 | 
					with the Program (or with a work based on the Program) on a volume of
 | 
				
			||||||
 | 
					a storage or distribution medium does not bring the other work under
 | 
				
			||||||
 | 
					the scope of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  3. You may copy and distribute the Program (or a work based on it,
 | 
				
			||||||
 | 
					under Section 2) in object code or executable form under the terms of
 | 
				
			||||||
 | 
					Sections 1 and 2 above provided that you also do one of the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    a) Accompany it with the complete corresponding machine-readable
 | 
				
			||||||
 | 
					    source code, which must be distributed under the terms of Sections
 | 
				
			||||||
 | 
					    1 and 2 above on a medium customarily used for software interchange; or,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b) Accompany it with a written offer, valid for at least three
 | 
				
			||||||
 | 
					    years, to give any third party, for a charge no more than your
 | 
				
			||||||
 | 
					    cost of physically performing source distribution, a complete
 | 
				
			||||||
 | 
					    machine-readable copy of the corresponding source code, to be
 | 
				
			||||||
 | 
					    distributed under the terms of Sections 1 and 2 above on a medium
 | 
				
			||||||
 | 
					    customarily used for software interchange; or,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c) Accompany it with the information you received as to the offer
 | 
				
			||||||
 | 
					    to distribute corresponding source code.  (This alternative is
 | 
				
			||||||
 | 
					    allowed only for noncommercial distribution and only if you
 | 
				
			||||||
 | 
					    received the program in object code or executable form with such
 | 
				
			||||||
 | 
					    an offer, in accord with Subsection b above.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The source code for a work means the preferred form of the work for
 | 
				
			||||||
 | 
					making modifications to it.  For an executable work, complete source
 | 
				
			||||||
 | 
					code means all the source code for all modules it contains, plus any
 | 
				
			||||||
 | 
					associated interface definition files, plus the scripts used to
 | 
				
			||||||
 | 
					control compilation and installation of the executable.  However, as a
 | 
				
			||||||
 | 
					special exception, the source code distributed need not include
 | 
				
			||||||
 | 
					anything that is normally distributed (in either source or binary
 | 
				
			||||||
 | 
					form) with the major components (compiler, kernel, and so on) of the
 | 
				
			||||||
 | 
					operating system on which the executable runs, unless that component
 | 
				
			||||||
 | 
					itself accompanies the executable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If distribution of executable or object code is made by offering
 | 
				
			||||||
 | 
					access to copy from a designated place, then offering equivalent
 | 
				
			||||||
 | 
					access to copy the source code from the same place counts as
 | 
				
			||||||
 | 
					distribution of the source code, even though third parties are not
 | 
				
			||||||
 | 
					compelled to copy the source along with the object code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  4. You may not copy, modify, sublicense, or distribute the Program
 | 
				
			||||||
 | 
					except as expressly provided under this License.  Any attempt
 | 
				
			||||||
 | 
					otherwise to copy, modify, sublicense or distribute the Program is
 | 
				
			||||||
 | 
					void, and will automatically terminate your rights under this License.
 | 
				
			||||||
 | 
					However, parties who have received copies, or rights, from you under
 | 
				
			||||||
 | 
					this License will not have their licenses terminated so long as such
 | 
				
			||||||
 | 
					parties remain in full compliance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  5. You are not required to accept this License, since you have not
 | 
				
			||||||
 | 
					signed it.  However, nothing else grants you permission to modify or
 | 
				
			||||||
 | 
					distribute the Program or its derivative works.  These actions are
 | 
				
			||||||
 | 
					prohibited by law if you do not accept this License.  Therefore, by
 | 
				
			||||||
 | 
					modifying or distributing the Program (or any work based on the
 | 
				
			||||||
 | 
					Program), you indicate your acceptance of this License to do so, and
 | 
				
			||||||
 | 
					all its terms and conditions for copying, distributing or modifying
 | 
				
			||||||
 | 
					the Program or works based on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  6. Each time you redistribute the Program (or any work based on the
 | 
				
			||||||
 | 
					Program), the recipient automatically receives a license from the
 | 
				
			||||||
 | 
					original licensor to copy, distribute or modify the Program subject to
 | 
				
			||||||
 | 
					these terms and conditions.  You may not impose any further
 | 
				
			||||||
 | 
					restrictions on the recipients' exercise of the rights granted herein.
 | 
				
			||||||
 | 
					You are not responsible for enforcing compliance by third parties to
 | 
				
			||||||
 | 
					this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  7. If, as a consequence of a court judgment or allegation of patent
 | 
				
			||||||
 | 
					infringement or for any other reason (not limited to patent issues),
 | 
				
			||||||
 | 
					conditions are imposed on you (whether by court order, agreement or
 | 
				
			||||||
 | 
					otherwise) that contradict the conditions of this License, they do not
 | 
				
			||||||
 | 
					excuse you from the conditions of this License.  If you cannot
 | 
				
			||||||
 | 
					distribute so as to satisfy simultaneously your obligations under this
 | 
				
			||||||
 | 
					License and any other pertinent obligations, then as a consequence you
 | 
				
			||||||
 | 
					may not distribute the Program at all.  For example, if a patent
 | 
				
			||||||
 | 
					license would not permit royalty-free redistribution of the Program by
 | 
				
			||||||
 | 
					all those who receive copies directly or indirectly through you, then
 | 
				
			||||||
 | 
					the only way you could satisfy both it and this License would be to
 | 
				
			||||||
 | 
					refrain entirely from distribution of the Program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If any portion of this section is held invalid or unenforceable under
 | 
				
			||||||
 | 
					any particular circumstance, the balance of the section is intended to
 | 
				
			||||||
 | 
					apply and the section as a whole is intended to apply in other
 | 
				
			||||||
 | 
					circumstances.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is not the purpose of this section to induce you to infringe any
 | 
				
			||||||
 | 
					patents or other property right claims or to contest validity of any
 | 
				
			||||||
 | 
					such claims; this section has the sole purpose of protecting the
 | 
				
			||||||
 | 
					integrity of the free software distribution system, which is
 | 
				
			||||||
 | 
					implemented by public license practices.  Many people have made
 | 
				
			||||||
 | 
					generous contributions to the wide range of software distributed
 | 
				
			||||||
 | 
					through that system in reliance on consistent application of that
 | 
				
			||||||
 | 
					system; it is up to the author/donor to decide if he or she is willing
 | 
				
			||||||
 | 
					to distribute software through any other system and a licensee cannot
 | 
				
			||||||
 | 
					impose that choice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This section is intended to make thoroughly clear what is believed to
 | 
				
			||||||
 | 
					be a consequence of the rest of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  8. If the distribution and/or use of the Program is restricted in
 | 
				
			||||||
 | 
					certain countries either by patents or by copyrighted interfaces, the
 | 
				
			||||||
 | 
					original copyright holder who places the Program under this License
 | 
				
			||||||
 | 
					may add an explicit geographical distribution limitation excluding
 | 
				
			||||||
 | 
					those countries, so that distribution is permitted only in or among
 | 
				
			||||||
 | 
					countries not thus excluded.  In such case, this License incorporates
 | 
				
			||||||
 | 
					the limitation as if written in the body of this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  9. The Free Software Foundation may publish revised and/or new versions
 | 
				
			||||||
 | 
					of the General Public License from time to time.  Such new versions will
 | 
				
			||||||
 | 
					be similar in spirit to the present version, but may differ in detail to
 | 
				
			||||||
 | 
					address new problems or concerns.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each version is given a distinguishing version number.  If the Program
 | 
				
			||||||
 | 
					specifies a version number of this License which applies to it and "any
 | 
				
			||||||
 | 
					later version", you have the option of following the terms and conditions
 | 
				
			||||||
 | 
					either of that version or of any later version published by the Free
 | 
				
			||||||
 | 
					Software Foundation.  If the Program does not specify a version number of
 | 
				
			||||||
 | 
					this License, you may choose any version ever published by the Free Software
 | 
				
			||||||
 | 
					Foundation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  10. If you wish to incorporate parts of the Program into other free
 | 
				
			||||||
 | 
					programs whose distribution conditions are different, write to the author
 | 
				
			||||||
 | 
					to ask for permission.  For software which is copyrighted by the Free
 | 
				
			||||||
 | 
					Software Foundation, write to the Free Software Foundation; we sometimes
 | 
				
			||||||
 | 
					make exceptions for this.  Our decision will be guided by the two goals
 | 
				
			||||||
 | 
					of preserving the free status of all derivatives of our free software and
 | 
				
			||||||
 | 
					of promoting the sharing and reuse of software generally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								    NO WARRANTY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 | 
				
			||||||
 | 
					FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 | 
				
			||||||
 | 
					OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 | 
				
			||||||
 | 
					PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 | 
				
			||||||
 | 
					OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 | 
				
			||||||
 | 
					TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 | 
				
			||||||
 | 
					PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 | 
				
			||||||
 | 
					REPAIR OR CORRECTION.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 | 
				
			||||||
 | 
					WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 | 
				
			||||||
 | 
					REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 | 
				
			||||||
 | 
					INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 | 
				
			||||||
 | 
					OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 | 
				
			||||||
 | 
					TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 | 
				
			||||||
 | 
					YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 | 
				
			||||||
 | 
					PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 | 
				
			||||||
 | 
					POSSIBILITY OF SUCH DAMAGES.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							     END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    How to Apply These Terms to Your New Programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  If you develop a new program, and you want it to be of the greatest
 | 
				
			||||||
 | 
					possible use to the public, the best way to achieve this is to make it
 | 
				
			||||||
 | 
					free software which everyone can redistribute and change under these terms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  To do so, attach the following notices to the program.  It is safest
 | 
				
			||||||
 | 
					to attach them to the start of each source file to most effectively
 | 
				
			||||||
 | 
					convey the exclusion of warranty; and each file should have at least
 | 
				
			||||||
 | 
					the "copyright" line and a pointer to where the full notice is found.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <one line to give the program's name and a brief idea of what it does.>
 | 
				
			||||||
 | 
					    Copyright (C) 19yy  <name of author>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					    along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also add information on how to contact you by electronic and paper mail.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the program is interactive, make it output a short notice like this
 | 
				
			||||||
 | 
					when it starts in an interactive mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Gnomovision version 69, Copyright (C) 19yy name of author
 | 
				
			||||||
 | 
					    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 | 
				
			||||||
 | 
					    This is free software, and you are welcome to redistribute it
 | 
				
			||||||
 | 
					    under certain conditions; type `show c' for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The hypothetical commands `show w' and `show c' should show the appropriate
 | 
				
			||||||
 | 
					parts of the General Public License.  Of course, the commands you use may
 | 
				
			||||||
 | 
					be called something other than `show w' and `show c'; they could even be
 | 
				
			||||||
 | 
					mouse-clicks or menu items--whatever suits your program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should also get your employer (if you work as a programmer) or your
 | 
				
			||||||
 | 
					school, if any, to sign a "copyright disclaimer" for the program, if
 | 
				
			||||||
 | 
					necessary.  Here is a sample; alter the names:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 | 
				
			||||||
 | 
					  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <signature of Ty Coon>, 1 April 1989
 | 
				
			||||||
 | 
					  Ty Coon, President of Vice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This General Public License does not permit incorporating your program into
 | 
				
			||||||
 | 
					proprietary programs.  If your program is a subroutine library, you may
 | 
				
			||||||
 | 
					consider it more useful to permit linking proprietary applications with the
 | 
				
			||||||
 | 
					library.  If this is what you want to do, use the GNU Library General
 | 
				
			||||||
 | 
					Public License instead of this License.
 | 
				
			||||||
							
								
								
									
										329
									
								
								UVconfig.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								UVconfig.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,329 @@
 | 
				
			||||||
 | 
					# UVconfig: Reads config files and tests configuration
 | 
				
			||||||
 | 
					# Used by all components
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package UVconfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Net::Domain qw(hostname hostfqdn hostdomain);
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					use vars qw(@ISA @EXPORT $VERSION $usevote_version %config %messages
 | 
				
			||||||
 | 
					            @rules @groups $bdsg_regexp $bdsg2_regexp %ids %functions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require Exporter;
 | 
				
			||||||
 | 
					@ISA = qw(Exporter);
 | 
				
			||||||
 | 
					@EXPORT = qw($usevote_version %config %messages @rules @groups
 | 
				
			||||||
 | 
					             $bdsg_regexp $bdsg2_regexp %ids %functions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Module version
 | 
				
			||||||
 | 
					$VERSION = "0.18";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Usevote version
 | 
				
			||||||
 | 
					$usevote_version = "UseVoteGer 4.09";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub read_config {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my ($cfgfile, $redir_errors) = @_;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  # Default configuration options (overwritten in usevote.cfg)
 | 
				
			||||||
 | 
					  %config = (votefile             => "votes",
 | 
				
			||||||
 | 
					             votename             => "unkonfiguriertes Usevote",
 | 
				
			||||||
 | 
					             resultfile           => "ergebnis.alle",
 | 
				
			||||||
 | 
					             rulefile             => "usevote.rul",
 | 
				
			||||||
 | 
					             badaddrfile          => "mailpatterns.cfg",
 | 
				
			||||||
 | 
					             messagefile          => "messages.cfg",
 | 
				
			||||||
 | 
					             idfile               => "scheinkennungen",
 | 
				
			||||||
 | 
					             requestfile          => "anforderung",
 | 
				
			||||||
 | 
					             errorfile            => "errors.log",
 | 
				
			||||||
 | 
					             lockfile             => "usevote.lock",
 | 
				
			||||||
 | 
					             replyto              => 0,
 | 
				
			||||||
 | 
					             personal             => 0,
 | 
				
			||||||
 | 
					             proportional         => 0,
 | 
				
			||||||
 | 
					             bdsg                 => 0,
 | 
				
			||||||
 | 
					             onestep              => 0,
 | 
				
			||||||
 | 
					             multigroup           => 0,
 | 
				
			||||||
 | 
					             voteack              => 1,
 | 
				
			||||||
 | 
					             voteaccount          => "<> (unkonfiguriertes Usevote)",
 | 
				
			||||||
 | 
					             mailfrom             => "<> (unkonfiguriertes Usevote)",
 | 
				
			||||||
 | 
					             envelopefrom         => "<>",
 | 
				
			||||||
 | 
					             mailstart            => "^From ",
 | 
				
			||||||
 | 
					             archivedir           => "fertig",
 | 
				
			||||||
 | 
					             tmpdir               => "tmp",
 | 
				
			||||||
 | 
					             templatedir          => "templates",
 | 
				
			||||||
 | 
					             formats              => "UVformats.pm",
 | 
				
			||||||
 | 
					             domailfile           => "tmp/domail",
 | 
				
			||||||
 | 
					             controlfile          => "tmp/ack.control",
 | 
				
			||||||
 | 
					             mailcmd              => "sendmail -oi -oem",
 | 
				
			||||||
 | 
					             mailcc               => "",
 | 
				
			||||||
 | 
					             sleepcmd             => "sleep 1",
 | 
				
			||||||
 | 
					             clearcmd             => "clear",
 | 
				
			||||||
 | 
					             pager                => "less",
 | 
				
			||||||
 | 
					             pop3                 => 0,
 | 
				
			||||||
 | 
					             pop3server           => "localhost",
 | 
				
			||||||
 | 
					             pop3port             => 110,
 | 
				
			||||||
 | 
					             pop3user             => "default",
 | 
				
			||||||
 | 
					             pop3pass             => "default",
 | 
				
			||||||
 | 
					             pop3delete           => 0,
 | 
				
			||||||
 | 
					             pop3uidlcache        => "uidlcache",
 | 
				
			||||||
 | 
					             pop3server_req       => "localhost",
 | 
				
			||||||
 | 
					             pop3port_req         => 110,
 | 
				
			||||||
 | 
					             pop3user_req         => "default",
 | 
				
			||||||
 | 
					             pop3pass_req         => "default",
 | 
				
			||||||
 | 
					             pop3delete_req       => 0,
 | 
				
			||||||
 | 
					             pop3uidlcache_req    => "uidlcache_req",
 | 
				
			||||||
 | 
					             pop3server_bounce    => "localhost",
 | 
				
			||||||
 | 
					             pop3port_bounce      => 110,
 | 
				
			||||||
 | 
					             pop3user_bounce      => "default",
 | 
				
			||||||
 | 
					             pop3pass_bounce      => "default",
 | 
				
			||||||
 | 
					             pop3delete_bounce    => 0,
 | 
				
			||||||
 | 
					             pop3uidlcache_bounce => 'uidlcache_bounce',
 | 
				
			||||||
 | 
					             smtp                 => 0,
 | 
				
			||||||
 | 
					             smtpserver           => 'localhost',
 | 
				
			||||||
 | 
					             smtpport             => 25,
 | 
				
			||||||
 | 
					             smtphelo             => hostfqdn(),
 | 
				
			||||||
 | 
					             fqdn                 => hostfqdn(),
 | 
				
			||||||
 | 
					             smtpauth             => 0,
 | 
				
			||||||
 | 
					             smtpuser             => '',
 | 
				
			||||||
 | 
					             smtppass             => '',
 | 
				
			||||||
 | 
					             name_re              => '[a-zA-ZäöüÄÖÜß-]{2,} +.*[a-zA-ZäöüÄÖÜß]{2,}',
 | 
				
			||||||
 | 
					             ja_stimme            => '(J\s*A|J|(D\s*A\s*)?F\s*U\s*E\s*R)',
 | 
				
			||||||
 | 
					             nein_stimme          => '(N\s*E\s*I\s*N|N|(D\s*A\s*)?G\s*E\s*G\s*E\s*N)',
 | 
				
			||||||
 | 
					             enth_stimme          => '(E|E\s*N\s*T\s*H\s*A\s*L\s*T\s*U\s*N\s*G)',
 | 
				
			||||||
 | 
					             ann_stimme           => 'A\s*N\s*N\s*U\s*L\s*L\s*I\s*E\s*R\s*U\s*N\s*G',
 | 
				
			||||||
 | 
					             condition1           => '$yes>=2*$no', # twice as many yes as no
 | 
				
			||||||
 | 
					             condition2           => '$yes>=60',    # min 60 yes votes
 | 
				
			||||||
 | 
					             prop_formula         => '$yes/$no',
 | 
				
			||||||
 | 
					             tpl_ack_mail         => 'ack-mail',
 | 
				
			||||||
 | 
					             tpl_bouncelist       => 'bouncelist',
 | 
				
			||||||
 | 
					             tpl_mailheader       => 'mailheader',
 | 
				
			||||||
 | 
					             tpl_result_multi     => 'result-multi',
 | 
				
			||||||
 | 
					             tpl_result_single    => 'result-single',
 | 
				
			||||||
 | 
					             tpl_result_prop      => 'result-proportional',
 | 
				
			||||||
 | 
					             tpl_votes_multi      => 'votes-multi',
 | 
				
			||||||
 | 
					             tpl_votes_single     => 'votes-single',
 | 
				
			||||||
 | 
					             tpl_voterlist        => 'voterlist',
 | 
				
			||||||
 | 
					             tpl_ballot           => 'ballot',
 | 
				
			||||||
 | 
					             tpl_ballot_request   => 'ballot-request',
 | 
				
			||||||
 | 
					             tpl_ballot_personal  => 'ballot-personal',
 | 
				
			||||||
 | 
					             tpl_addr_reg         => 'address-not-registered',
 | 
				
			||||||
 | 
					             tpl_no_ballotid      => 'no-ballotid',
 | 
				
			||||||
 | 
					             tpl_wrong_ballotid   => 'wrong-ballotid',
 | 
				
			||||||
 | 
					             tpl_bdsg_error       => 'bdsg-error',
 | 
				
			||||||
 | 
					             tpl_cancelled        => 'cancelled',
 | 
				
			||||||
 | 
					             tpl_invalid_account  => 'invalid-account',
 | 
				
			||||||
 | 
					             tpl_invalid_name     => 'invalid-name',
 | 
				
			||||||
 | 
					             tpl_multiple_votes   => 'multiple-votes',
 | 
				
			||||||
 | 
					             tpl_no_ballot        => 'no-ballot',
 | 
				
			||||||
 | 
					             tpl_no_votes         => 'no-votes',
 | 
				
			||||||
 | 
					             tpl_rule_violated    => 'rule-violated',
 | 
				
			||||||
 | 
					             begin_divider        => 'Alles vor dieser Zeile bitte loeschen',
 | 
				
			||||||
 | 
					             end_divider          => 'Alles nach dieser Zeile bitte loeschen',
 | 
				
			||||||
 | 
					             nametext             => 'Dein Realname, falls nicht im FROM-Header:',
 | 
				
			||||||
 | 
					             nametext2            => 'Waehlername:',
 | 
				
			||||||
 | 
					             addresstext          => 'Waehleradresse:',
 | 
				
			||||||
 | 
					             ballotidtext         => 'Wahlscheinkennung:',
 | 
				
			||||||
 | 
					             bdsgtext             => 'Datenschutzklausel - Zustimmung',
 | 
				
			||||||
 | 
					             bdsgfile             => 'bdsgtext.cfg',
 | 
				
			||||||
 | 
					             rightmargin          => 72,
 | 
				
			||||||
 | 
					             usevote_version      => $usevote_version); # needed for use in templates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # read config
 | 
				
			||||||
 | 
					  read_file($cfgfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # read message file
 | 
				
			||||||
 | 
					  open (RES, "<$config{messagefile}")
 | 
				
			||||||
 | 
					     or die "Could not read message file $config{messagefile}!\n\n";
 | 
				
			||||||
 | 
					  my @lines = <RES>;
 | 
				
			||||||
 | 
					  close(RES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $line (@lines) {
 | 
				
			||||||
 | 
					    chomp($line);
 | 
				
			||||||
 | 
					    $line =~ s/^#.*//;        # Delete comments
 | 
				
			||||||
 | 
					    if ($line =~ m/^\s*([A-Za-z0-9_-]+)\s*=\s*(.+)\s*$/){
 | 
				
			||||||
 | 
					      $messages{$1} = $2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # missing "groupX =" lines in config file?
 | 
				
			||||||
 | 
					  die UVmessage::get("CONF_NOGROUPS", CONFIGFILE=>$cfgfile) . "\n\n" unless (@groups);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # redirect errors to a file if desired by calling script
 | 
				
			||||||
 | 
					  open (STDERR, ">$config{errorfile}") if ($redir_errors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # check for data protection law? read text for ballot
 | 
				
			||||||
 | 
					  parse_bdsgtext() if ($config{bdsg});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # personalized ballots? read ballot IDs
 | 
				
			||||||
 | 
					  read_ballot_ids() if ($config{personal});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  load_formats() if ($config{formats});
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# read config file                                                           #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub read_file {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $cfgfile = shift;
 | 
				
			||||||
 | 
					  my $CONFIG;
 | 
				
			||||||
 | 
					  open ($CONFIG, "<$cfgfile") or die "Could not find config file $cfgfile!\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (<$CONFIG>) {
 | 
				
			||||||
 | 
					    next if (/^#/);     # line is a comment
 | 
				
			||||||
 | 
					    chomp;              # delete \n
 | 
				
			||||||
 | 
					    s/\r//;             # delete \r if present
 | 
				
			||||||
 | 
					    s/([^\\])#.*$/$1/;  # Remove comments not starting at beginning of line.
 | 
				
			||||||
 | 
					                        # (ignore escaped comment sign \#)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (/^include (\S+)$/) {
 | 
				
			||||||
 | 
					      # include other config file
 | 
				
			||||||
 | 
					      read_file($1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif (my($key, $value) = split (/\s*=\s*/, $_, 2)) {
 | 
				
			||||||
 | 
					      # delete trailing spaces
 | 
				
			||||||
 | 
					      $value =~ s/\s*$//;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # evaluate quotation marks
 | 
				
			||||||
 | 
					      $value =~ s/^\"([^\"]+[^\\\"])\".*$/$1/;
 | 
				
			||||||
 | 
					      $value =~ s/\\"/"/g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ($key =~ /^group(\d+)$/) {
 | 
				
			||||||
 | 
					        my $num = $1;
 | 
				
			||||||
 | 
					        $groups[$num-1] = $value;    # internal index starts at 0
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $config{$key} = $value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  close ($CONFIG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# parse data protection law texts                                            #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub parse_bdsgtext {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  open (BDSG, "<$config{bdsgfile}") or die UVmessage::get("CONF_NOBDSGFILE",
 | 
				
			||||||
 | 
					                            ('BDSGFILE' => "$config{bdsgfile}")) . "\n\n";
 | 
				
			||||||
 | 
					  my @bdsg = <BDSG>;
 | 
				
			||||||
 | 
					  close BDSG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $config{bdsginfo} = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $line (@bdsg) {
 | 
				
			||||||
 | 
					    $config{bdsginfo} .= $line unless ($line =~ /^\s*#/);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $bdsgtmp = $config{bdsginfo};
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\"/\\\"/g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\'/\\\'/g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\(/\\\(/g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\)/\\\)/g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\[/\\\[/g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\]/\\\]/g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\./\\\./g;
 | 
				
			||||||
 | 
					  $bdsgtmp =~ s/\!/\\\!/g;
 | 
				
			||||||
 | 
					  my @bdsgtext = split(' ', $bdsgtmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Build Regular Expression from single words.
 | 
				
			||||||
 | 
					  # There has to be at least a space between two words, additional characters
 | 
				
			||||||
 | 
					  # are allowed, e.g. quotation marks (but no letters)
 | 
				
			||||||
 | 
					  $bdsg_regexp = join('\s\W*?', @bdsgtext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Build Regular Expression from $config{bdsgtext}
 | 
				
			||||||
 | 
					  $bdsg2_regexp = join('\s\W*?', split(' ', $config{bdsgtext}));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Read suspicious mail addresses (normally mailpatterns.cfg)                 #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub read_badaddr {
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  my @bad_addr = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  open (BADADDR, "<$config{badaddrfile}") or die 
 | 
				
			||||||
 | 
					    UVmessage::get("CONF_NOBADADDR",(BADADDRFILE => $config{badaddrfile})) . "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (<BADADDR>) {
 | 
				
			||||||
 | 
					    chomp;
 | 
				
			||||||
 | 
					    # Comment line? Not only whitespaces?
 | 
				
			||||||
 | 
					    if (/^[^#]/ && /[^\s]/) {
 | 
				
			||||||
 | 
					      push(@bad_addr, $_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  close (BADADDR);
 | 
				
			||||||
 | 
					  return @bad_addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Read ballot IDs                                                            #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub read_ballot_ids {
 | 
				
			||||||
 | 
					  # open file with ballot ids
 | 
				
			||||||
 | 
					  open(FILE, "<$config{idfile}") or return 1;
 | 
				
			||||||
 | 
					  while (<FILE>) {
 | 
				
			||||||
 | 
					    chomp;
 | 
				
			||||||
 | 
					    # Format: mailaddress (whitespace) ballot ID
 | 
				
			||||||
 | 
					    if (/^(.+@.+)\s+([a-z0-9]+)/) {
 | 
				
			||||||
 | 
					      # $1=mailadresse, $2=ballot ID
 | 
				
			||||||
 | 
					      $ids{$1} = $2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  close(FILE);
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Funktionen für Templates laden                                             #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub load_formats {
 | 
				
			||||||
 | 
					  my $modules = $config{formats};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @modules = split(/\s*,\s*/, $modules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $module (@modules){
 | 
				
			||||||
 | 
					    if (-r $module){
 | 
				
			||||||
 | 
					      require $module;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# config test                                                                #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub test_config {
 | 
				
			||||||
 | 
					  print UVmessage::get("CONF_CONFIG"), "\n\n";
 | 
				
			||||||
 | 
					  foreach my $option (keys %config) {
 | 
				
			||||||
 | 
					    print "$option = $config{$option}\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print "\n", UVmessage::get("CONF_TEST_RULES");
 | 
				
			||||||
 | 
					  if (@rules) {
 | 
				
			||||||
 | 
					    print "\n\n";
 | 
				
			||||||
 | 
					    for (my $n=0; $n<@rules; $n++) {
 | 
				
			||||||
 | 
					      my $text = UVrules::rule_print($n);
 | 
				
			||||||
 | 
					      print $text;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    print "\n";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    print UVmessage::get("CONF_NO_RULES"), "\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
							
								
								
									
										566
									
								
								UVformats.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								UVformats.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,566 @@
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					  package UVformats;
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 NAME
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UVformats - Methoden zur Stringformatierung
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 SYNOPSIS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  value  <name-of-key>
 | 
				
			||||||
 | 
					  append <name-of-key>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fill-left   <width> <character>
 | 
				
			||||||
 | 
					  fill-right  <width> <character>
 | 
				
			||||||
 | 
					  fill-center <width> <character>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  justify	 <name-of-key> <width>
 | 
				
			||||||
 | 
					  justify-before <name-of-key> <width>
 | 
				
			||||||
 | 
					  justify-behind <name-of-key> <width>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  first-words  <width>
 | 
				
			||||||
 | 
					  drop-words   <width>
 | 
				
			||||||
 | 
					  create-lines <width>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  multi-graph <width> <position> <count>
 | 
				
			||||||
 | 
					  multi-line  <width> <count>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  quote <string>
 | 
				
			||||||
 | 
					  replace <original-string> <replacement-string>
 | 
				
			||||||
 | 
					  sprintf <format-string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  generate_date_header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 DESCRIPTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dieses Modul stellt verschiedenste Methoden bereit, um die Strings in 
 | 
				
			||||||
 | 
					den Templates auf die unterschiedlichste Art zu formatieren. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dieses Modul beschraenkt sich auf die Beschreibung der Funktionen. Ihre
 | 
				
			||||||
 | 
					Einbindung wird in UVtemplates beschrieben.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=over 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use vars qw(@ISA @EXPORT $VERSION $functions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Exporter;
 | 
				
			||||||
 | 
					$VERSION = 0.01;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@ISA = qw(Exporter);
 | 
				
			||||||
 | 
					@EXPORT = qw( getFunctions );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Text::Wrap;
 | 
				
			||||||
 | 
					#use POSIX qw(strftime);
 | 
				
			||||||
 | 
					use Email::Date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub getFunctions{
 | 
				
			||||||
 | 
					  return $functions;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					=item value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gibt den Wert eines Schluessel zurueck. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  new-key := value 'old-key' | <other-functions> ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Diese Funktion sollte dann eingesetzt werden, wenn man einen virtuellen
 | 
				
			||||||
 | 
					Schluessel erzeugen will. D.h. der Bezeichner nicht im Template als
 | 
				
			||||||
 | 
					Schluessel vorhanden ist. Durch den Einsatz von value wird der Wert eines
 | 
				
			||||||
 | 
					anderen Schluessel kopiert und kann dann weiter formatiert werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub value{
 | 
				
			||||||
 | 
					  my ($data, $value, $key) = @_;
 | 
				
			||||||
 | 
					  return $data->getKey($key);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item append
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Den Wert eines anderen Schluessels an den bisherigen String anhaengen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ... | append 'other-key' | ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Per default wird als Trenner der beiden String ein Leerzeichen verwendet.
 | 
				
			||||||
 | 
					Soll dieses entfallen oder ein anderes Zeichen benutzt werden, so kann
 | 
				
			||||||
 | 
					ein dementsprechender drittere Parameter angegeben werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ... | append 'other-key' ''  | ...
 | 
				
			||||||
 | 
					  ... | append 'other-key' '_' | ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Im ersten Beispiel wird der Wert von C<other-key> nahtlos hinzugefuegt.
 | 
				
			||||||
 | 
					Im zweiten statt des Leerzeichens '_' benutzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub append{
 | 
				
			||||||
 | 
					  my ($data, $value, $key, $sep) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $sep = ' ' unless defined($sep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value. $sep. $data->getConvKey($key);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item fill-left, fill-right, fill-center
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fuellt den String entsprechend mit Zeichen auf bis die gewuenschte
 | 
				
			||||||
 | 
					Laenge erreicht ist. Bei C<fill-left> werden die Zeichen vorranggestellt,
 | 
				
			||||||
 | 
					bei C<fill-right> angehaengt. C<fill-center> verteilt die Zeichen 
 | 
				
			||||||
 | 
					gleichmaessig vor und nach dem String.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ... | fill-left 72 '.' | ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wird kein zweiter Parameter angegeben, wird automatisch das Leerzeichen
 | 
				
			||||||
 | 
					benutzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ... | fill-right 60 | ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ist der String bereits laenger als gewuenscht, wird er nicht weiter
 | 
				
			||||||
 | 
					veraendert und auch nicht verkuerzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub fill_left{ 
 | 
				
			||||||
 | 
					  my ($data, $value, $width, $char) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $width ||= 72;
 | 
				
			||||||
 | 
					  $char  = ' ' unless (defined($char) && length($char) == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $fill = $width - length($value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $value = $char x $fill . $value if ($fill > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub fill_right{ 
 | 
				
			||||||
 | 
					  my ($data, $value, $width, $char) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $width ||= 72;
 | 
				
			||||||
 | 
					  $char  ||= ' ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $fill = $width - length($value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $value .= $char x $fill if ($fill > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub fill_both{ 
 | 
				
			||||||
 | 
					  my ($data, $value, $width, $char) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $width ||= 72;
 | 
				
			||||||
 | 
					  $char  ||= ' ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $fill = $width - length($value);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ($fill > 0){
 | 
				
			||||||
 | 
					    my $left  = int($fill / 2);
 | 
				
			||||||
 | 
					    my $right = $fill - $left;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $value = $char x $left . $value . $char x $right; 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item justify, justify-before, justify-behind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fuegt zwischen den existierenden String und dem Wert des angegebenen 
 | 
				
			||||||
 | 
					Schluessel genau so viele Leerzeichen ein, damit die gewuenschte 
 | 
				
			||||||
 | 
					Stringlaenge erreicht wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ... | justify-behind 'key' 72 | ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<justify-behind> haengt den Wert des Schluessel an das Ende des Strings,
 | 
				
			||||||
 | 
					C<justify-before> stellt es davor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  justify-behind: existing-string.........value-of-key
 | 
				
			||||||
 | 
					  justify-before: value-of-key.........existing-string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<justify> ist lediglich ein Alias auf C<justify-behind>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Sind die beiden Strings zusammen länger als die gewuenschte
 | 
				
			||||||
 | 
					Zeilenlaenge, wird automatisch einen Zeilenbruch eingefuegt
 | 
				
			||||||
 | 
					und beide Zeilen entsprechend mit Leerzeichen gefuellt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  very-very-very-long-existing-string.........\n
 | 
				
			||||||
 | 
					  ...................and-a-too-long-new-string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub justify_behind{
 | 
				
			||||||
 | 
					  my ($data, $value, $key, $width) = @_;
 | 
				
			||||||
 | 
					  return _justify( $value, $data->getConvKey($key), $width);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub justify_before{
 | 
				
			||||||
 | 
					  my ($data, $value, $key, $width) = @_;
 | 
				
			||||||
 | 
					  return _justify( $data->getConvKey($key), $value, $width);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _justify{
 | 
				
			||||||
 | 
					  my ($lval, $rval, $width) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $sep = ' ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (length($lval.$rval) >= $width ){
 | 
				
			||||||
 | 
					    # wir basteln zwei zeilen
 | 
				
			||||||
 | 
					    $lval .= $sep x ($width - length($lval));
 | 
				
			||||||
 | 
					    $rval = $sep x ($width - length($rval)) . $rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $lval."\n".$rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }else{
 | 
				
			||||||
 | 
					    my $fill = $width - length($lval) - length($rval);
 | 
				
			||||||
 | 
					    return $lval . $sep x $fill . $rval;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item first-words
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gibt nur die ersten Worte eines Strings zurueck, die vollstaendig
 | 
				
			||||||
 | 
					innerhalb der angegebenen Laenge liegen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub first_words{
 | 
				
			||||||
 | 
					  my ($data, $value, $width) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @words = split('\s+', $value);
 | 
				
			||||||
 | 
					  my $string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $string .= shift(@words);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while(@words && (length($string) + length($words[0]) + 1) < $width){
 | 
				
			||||||
 | 
					    $string .= ' ' . shift(@words);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item drop-words
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alle Woerter am Anfang des Strings entfernen, die komplett innerhalb
 | 
				
			||||||
 | 
					der angegebenen Laenge liegen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub drop_words{
 | 
				
			||||||
 | 
					  my ($data, $value, $width) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @words = split('\s+', $value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # das erste "Wort" immer verwerfen, egal wie lang es ist
 | 
				
			||||||
 | 
					  my $first  = shift(@words);
 | 
				
			||||||
 | 
					  my $length = length($first);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (@words && ( $length + length($words[0]) + 1 ) < $width ){
 | 
				
			||||||
 | 
					    $length += length($words[0]) + 1;
 | 
				
			||||||
 | 
					    shift(@words);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return join(' ', @words);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item create-lines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zerlegt einen String in einen Array, in dem die einzelnen Zeilen nicht
 | 
				
			||||||
 | 
					laenger als die gewuenschte Anzahl Zeichen sind.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  absatz := value 'key' | create-lines 72 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mit Hilfe dieser Funktion ist es moeglich, ueberlange Zeilen zu Absatzen
 | 
				
			||||||
 | 
					umzuformatieren.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die Funktion erzeugt intern eine Liste, die jeweils den Schluessel C<line>
 | 
				
			||||||
 | 
					mit dem entsprechenden String als Wert enthaelt. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Im Template wird der so Absatz dann mit Hilfe des Schleifen-Syntax
 | 
				
			||||||
 | 
					eingebunden:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [@absatz|[line]\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Achtung! Da die Funktion keinen String zurueckgibt, sollte sie am Ende
 | 
				
			||||||
 | 
					der Kette stehen, da die normalen Formatierungsfunktionen einen String
 | 
				
			||||||
 | 
					als Input erwartern!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub create_lines{
 | 
				
			||||||
 | 
					  my ($data, $value, $width) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @words = split('\s+', $value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @lines;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (@words){
 | 
				
			||||||
 | 
					    my $string .= shift(@words);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while(@words && (length($string) + length($words[0]) + 1) < $width){
 | 
				
			||||||
 | 
					      $string .= ' ' . shift(@words);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $new = $data->new( line => $string );
 | 
				
			||||||
 | 
					    push(@lines, $new);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return \@lines;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item multi-graph, multi-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Spezielle Funktionen, um eine bestimmte graphische Ausgabe fuer
 | 
				
			||||||
 | 
					Votings mit mehreren Abstimmungspunkten zu erzeugen:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Punkt 1 --------------------------+
 | 
				
			||||||
 | 
					  Punkt 2a ------------------------+|
 | 
				
			||||||
 | 
					  Punkt 2b -----------------------+||
 | 
				
			||||||
 | 
					  Punkt 3 -----------------------+|||
 | 
				
			||||||
 | 
					                                 ||||
 | 
				
			||||||
 | 
					  Name of Voter 1                jjnn
 | 
				
			||||||
 | 
					  Name of Voter 2                nnjj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<multi-graph> ist hierbei für die Formatierung der einzelnen Abstimmungspunkte 
 | 
				
			||||||
 | 
					zustaendig.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  multi-graph 'key' 'width' 'pos-key' 'max-key'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Der erste Parameter gibt den Schluessel an, dessen Wert als Abstimmungspunkt
 | 
				
			||||||
 | 
					ausgegeben werden soll. C<width> die Laenge des zu erzeugenden Strings.
 | 
				
			||||||
 | 
					C<pos-key> und C<max-key> sind die Namen der Schluessel, in denen stehen
 | 
				
			||||||
 | 
					muss, um den wievielten Abstimmungspunkt es sich handelt (per default 'pos')
 | 
				
			||||||
 | 
					und wieviele Abstimmungspunkte es insgesamt gibt ('anzpunkte').
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					C<multi-line> erzeugt einfach nur einen String in der gewuenschten
 | 
				
			||||||
 | 
					Laenge, der entsprechend der Anzahl der Abstimmungspunkte mit '|'
 | 
				
			||||||
 | 
					abschliesst.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub mgraph{
 | 
				
			||||||
 | 
					  my ($data, $value, $width, $pkey, $okey) = @_;
 | 
				
			||||||
 | 
					  return unless $data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $pos = $data->getKey($pkey || 'pos');
 | 
				
			||||||
 | 
					  my $of  = $data->getKey($okey || 'anzpunkte');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $gfx = '';
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  $gfx = ' ---'.'-' x ($of-$pos) .'+'. '|' x ($pos - 1) if ($pos && $of);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (length($value.$gfx) < $width){
 | 
				
			||||||
 | 
					    $value = ' ' x ($width - length($value.$gfx)) . $value . $gfx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }elsif (length($value.$gfx) > $width){
 | 
				
			||||||
 | 
					    my @lines = _wrap($value, $width - length($gfx));
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					    $value = shift(@lines) . $gfx;
 | 
				
			||||||
 | 
					    $value = ' ' x ($width - length($value)) . $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Hilfzeile erzeugen
 | 
				
			||||||
 | 
					    $gfx = '    '.' ' x ($of-$pos) . '|' x ($pos) if ($pos && $of);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach my $line (@lines){
 | 
				
			||||||
 | 
					      $value .= "\n".' ' x ($width - length($line.$gfx)) . $line . $gfx;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub mgline{
 | 
				
			||||||
 | 
					  my ($data, undef, $width, $okey) = @_;
 | 
				
			||||||
 | 
					  return unless $data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $of = $data->getKey($okey || 'anzpunkte') || 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return ' ' x ($width - $of) . '|' x $of;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _wrap{
 | 
				
			||||||
 | 
					  my ($string, $width) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @words = split('\s+', $string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @lines;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (@words){
 | 
				
			||||||
 | 
					    my $line .= shift(@words);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while(@words && (length($line) + length($words[0]) + 1) < $width){
 | 
				
			||||||
 | 
					      $line .= ' ' . shift(@words);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    push(@lines, $line);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return @lines;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item quote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Stellt in einem (mehrzeiligem) String jeder Zeile den gewuenschten
 | 
				
			||||||
 | 
					Quotestring voran.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  body := value 'body' | quote '> '
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub quote{
 | 
				
			||||||
 | 
					  my ($data, $value, $quotechar) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $quotechar = '> ' unless defined($quotechar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $value =~ s/^/$quotechar/mg;
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item replace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ersetzt in einem String ein oder mehrere Zeichen durch eine beliebige
 | 
				
			||||||
 | 
					Anzahl anderer Zeichen. Diese Funktion kann z.B. genutzt werden, um
 | 
				
			||||||
 | 
					beim Result die Mailadressen zu verfremden (Schutz vor Adress-Spidern).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mail := value 'mail' | replace '@' '-at-'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub replace{
 | 
				
			||||||
 | 
					  my ($data, $value, $original, $replacement) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $original = ' ' unless defined($original);
 | 
				
			||||||
 | 
					  $replacement = ' ' unless defined($replacement);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $value =~ s/\Q$original\E/$replacement/g;
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item sprintf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gibt Text oder Zahlen mittels der Funktion sprintf formatiert aus
 | 
				
			||||||
 | 
					(siehe "man 3 sprintf" oder "perldoc -f sprintf").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  proportion := value 'proportion' | sprintf '%6.3f'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub sprintf{
 | 
				
			||||||
 | 
					  my ($data, $value, $format) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $format = '%s' unless defined($format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return sprintf($format, $value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item generate_date_header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gibt ein Datum im RFC822-Format zur Verwendung im Date:-Header einer
 | 
				
			||||||
 | 
					Mail aus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  date := generate_date_header
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub generate_date_header{
 | 
				
			||||||
 | 
					  my ($data, $value, $format) = @_;
 | 
				
			||||||
 | 
					  #return strftime('%a, %d %b %Y %H:%M:%S %z', localtime);
 | 
				
			||||||
 | 
					  return format_date;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item generate_msgid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gibt eine Message-ID im RFC822-Format zur Verwendung im Message-ID:-Header
 | 
				
			||||||
 | 
					einer Mail aus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  msgid := generate_msgid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub generate_msgid{
 | 
				
			||||||
 | 
					  return ("<".$$.time().rand(999)."\@".$UVconfig::config{fqdn}.">");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BEGIN{
 | 
				
			||||||
 | 
					  %UVconfig::functions = ( %UVconfig::functions,
 | 
				
			||||||
 | 
					    value 		=> \&value,
 | 
				
			||||||
 | 
					    append		=> \&append,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'fill-left'  	=> \&fill_left,
 | 
				
			||||||
 | 
					    'fill-right' 	=> \&fill_right,
 | 
				
			||||||
 | 
					    'fill-both'  	=> \&fill_both,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    justify		=> \&justify_behind,
 | 
				
			||||||
 | 
					    'justify-behind'	=> \&justify_behind,
 | 
				
			||||||
 | 
					    'justify-before' 	=> \&justify_before,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'first-words' 	=> \&first_words,
 | 
				
			||||||
 | 
					    'drop-words' 	=> \&drop_words,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'create-lines' 	=> \&create_lines,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'multi-graph' 	=> \&mgraph,
 | 
				
			||||||
 | 
					    'multi-line'  	=> \&mgline,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'quote'             => \"e,
 | 
				
			||||||
 | 
					    'replace'           => \&replace,
 | 
				
			||||||
 | 
					    'sprintf'           => \&sprintf,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'generate-date-header' => \&generate_date_header,
 | 
				
			||||||
 | 
					    'generate-msgid'    => \&generate_msgid
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=back
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 SEE ALSO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					L<UVtemplate>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 AUTHOR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cornell Binder <cobi@dex.de>
 | 
				
			||||||
 | 
					Marc Langer <usevote@marclanger.de>
 | 
				
			||||||
							
								
								
									
										380
									
								
								UVmenu.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								UVmenu.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,380 @@
 | 
				
			||||||
 | 
					# UVmenu: menu for interaction with the votetaker
 | 
				
			||||||
 | 
					# Used by uvvote.pl, uvcfv.pl, uvcount.pl
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					package UVmenu;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					use UVrules;
 | 
				
			||||||
 | 
					use vars qw($VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Text::Wrap qw(wrap $columns);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					# Module version
 | 
				
			||||||
 | 
					$VERSION = "0.4";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Menu for interaction with the votetaker                                    #
 | 
				
			||||||
 | 
					# Parameters: votes list and header (references to arrays)                   #
 | 
				
			||||||
 | 
					#             Body, Mailadress, Name, Ballot ID (references to strings)      #
 | 
				
			||||||
 | 
					#             List of newly set fields (reference to array)                  #
 | 
				
			||||||
 | 
					#             List of errors to correct (Array-Ref)                          #
 | 
				
			||||||
 | 
					# Return Values: 'w': proceed                                                #
 | 
				
			||||||
 | 
					#                'i': ignore (don't save vote)                               #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub menu {
 | 
				
			||||||
 | 
					  my ($votes, $header, $body, $addr, $name, $ballot_id, $set, $errors) = @_;
 | 
				
			||||||
 | 
					  my $input = "";
 | 
				
			||||||
 | 
					  my $voter_addr = $$addr || '';
 | 
				
			||||||
 | 
					  my $voter_name = $$name || '';
 | 
				
			||||||
 | 
					  my @newvotes = @$votes;
 | 
				
			||||||
 | 
					  my $mailonly = 0;
 | 
				
			||||||
 | 
					  my %errors;
 | 
				
			||||||
 | 
					  $$ballot_id ||= '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $error (@$errors) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # unrecognized vote: extract group number und display warning
 | 
				
			||||||
 | 
					    if ($error =~ /^UnrecognizedVote #(\d+)#(.+)$/) {
 | 
				
			||||||
 | 
					      $errors{UnrecognizedVote} ||= UVmessage::get("MENU_UNRECOGNIZEDVOTE");
 | 
				
			||||||
 | 
					      $errors{UnrecognizedVote} .= "\n  " . UVmessage::get("MENU_UNRECOGNIZED_LIST")
 | 
				
			||||||
 | 
					                                          . " #$1: $2";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # violated rule: extract rule number and display warning
 | 
				
			||||||
 | 
					    } elsif ($error =~ /^ViolatedRule #(\d+)$/) {
 | 
				
			||||||
 | 
					      $errors{ViolatedRule} ||= UVmessage::get("MENU_VIOLATEDRULE", (RULE => "#$1"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      # special handling if called from uvballot.pl
 | 
				
			||||||
 | 
					      $mailonly = 1 if ($error =~ s/Ballot$//);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # get error message for this error from messages.cfg
 | 
				
			||||||
 | 
					      $errors{$error} = UVmessage::get("MENU_" . uc($error));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # This loop is only left by 'return'
 | 
				
			||||||
 | 
					  while (1) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    system($config{clearcmd});
 | 
				
			||||||
 | 
					    print UVmessage::get("MENU_PROBLEMS") . "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach my $error (keys %errors) {
 | 
				
			||||||
 | 
					      print "* $errors{$error}\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $menucaption = UVmessage::get("MENU_CAPTION");
 | 
				
			||||||
 | 
					    print "\n\n$menucaption\n";
 | 
				
			||||||
 | 
					    print "=" x length($menucaption), "\n\n";
 | 
				
			||||||
 | 
					    print "(1) ", UVmessage::get("MENU_SHOW_MAIL"), "\n\n",
 | 
				
			||||||
 | 
					          UVmessage::get("MENU_CHANGE_PROPERTIES"), "\n",
 | 
				
			||||||
 | 
					          "(2) ", UVmessage::get("MENU_ADDRESS"), " [$voter_addr]\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # don't print these options if called from uvcfv.pl
 | 
				
			||||||
 | 
					    unless ($mailonly) {
 | 
				
			||||||
 | 
					      print "(3) ", UVmessage::get("MENU_NAME"), " [$voter_name]\n";
 | 
				
			||||||
 | 
					      print "(4) ", UVmessage::get("MENU_VOTES"), " [", @$votes, "]\n";
 | 
				
			||||||
 | 
					      print "(5) ", UVmessage::get("MENU_BALLOT_ID"), " [$$ballot_id]\n"
 | 
				
			||||||
 | 
					        if ($config{personal});
 | 
				
			||||||
 | 
					      print "(6) ", UVmessage::get("MENU_BDSG"), "\n" if ($config{bdsg});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print "\n",
 | 
				
			||||||
 | 
					          "(i) ", UVmessage::get("MENU_IGNORE"), "\n",
 | 
				
			||||||
 | 
					          "(w) ", UVmessage::get("MENU_PROCEED"), "\n\n",
 | 
				
			||||||
 | 
					          UVmessage::get("MENU_PROMPT");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do { $input = <STDIN>; } until ($input);
 | 
				
			||||||
 | 
					    chomp $input;
 | 
				
			||||||
 | 
					    print "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # only accept 1, 2, i and w if called from uvcfv.pl
 | 
				
			||||||
 | 
					    next if ($mailonly && $input !~ /^[12iw]$/i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($input eq '1') {
 | 
				
			||||||
 | 
					      system($config{clearcmd});
 | 
				
			||||||
 | 
					      # ignore SIGPIPE (Bug in more and less)
 | 
				
			||||||
 | 
					      $SIG{PIPE} = 'IGNORE';
 | 
				
			||||||
 | 
					      open (MORE, "|$config{pager}");
 | 
				
			||||||
 | 
					      print MORE join("\n", @$header), "\n\n", $$body, "\n";
 | 
				
			||||||
 | 
					      close (MORE);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      print "\n", UVmessage::get("MENU_GETKEY");
 | 
				
			||||||
 | 
					      $input = <STDIN>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif ($input eq '2') {
 | 
				
			||||||
 | 
					      my $sel;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        print "[a] ", UVmessage::get("MENU_ADDRESS_OK"), "\n",
 | 
				
			||||||
 | 
					              "[b] ", UVmessage::get("MENU_ADDRESS_CHANGE"), "\n",
 | 
				
			||||||
 | 
					              "[c] ", UVmessage::get("MENU_ADDRESS_INVALID"), "\n\n",
 | 
				
			||||||
 | 
					              UVmessage::get("MENU_PROMPT");
 | 
				
			||||||
 | 
					        $sel = <STDIN>;
 | 
				
			||||||
 | 
					      } until ($sel =~ /^[abc]$/i);
 | 
				
			||||||
 | 
					      if ($sel =~ /^a$/i) {
 | 
				
			||||||
 | 
					        delete $errors{SuspiciousAccount};
 | 
				
			||||||
 | 
					        delete $errors{InvalidAddress};
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      } elsif ($sel =~ /^c$/i) {
 | 
				
			||||||
 | 
					        delete $errors{SuspiciousAccount};
 | 
				
			||||||
 | 
					        $errors{InvalidAddress} = UVmessage::get("MENU_INVALIDADDRESS") . " " .
 | 
				
			||||||
 | 
					                                  UVmessage::get("MENU_INVALIDADDRESS2");
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        print "\n", UVmessage::get("MENU_ADDRESS_PROMPT"), " ";
 | 
				
			||||||
 | 
					        $voter_addr = <STDIN>;
 | 
				
			||||||
 | 
					        chomp ($voter_addr);
 | 
				
			||||||
 | 
					      } until ($voter_addr);
 | 
				
			||||||
 | 
					      $$addr = $voter_addr;
 | 
				
			||||||
 | 
					      push (@$set, 'Adresse');
 | 
				
			||||||
 | 
					      delete $errors{SuspiciousAccount};
 | 
				
			||||||
 | 
					      delete $errors{InvalidAddress};
 | 
				
			||||||
 | 
					      check_ballotid(\%errors, \$voter_addr, $ballot_id, \%ids);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif ($input eq '3') {
 | 
				
			||||||
 | 
					      my $sel;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        print "[a] ", UVmessage::get("MENU_NAME_OK"), "\n",
 | 
				
			||||||
 | 
					              "[b] ", UVmessage::get("MENU_NAME_CHANGE"), "\n",
 | 
				
			||||||
 | 
					              "[c] ", UVmessage::get("MENU_NAME_INVALID"), "\n\n",
 | 
				
			||||||
 | 
					              UVmessage::get("MENU_PROMPT");
 | 
				
			||||||
 | 
					        $sel = <STDIN>;
 | 
				
			||||||
 | 
					      } until ($sel =~ /^[abc]$/i);
 | 
				
			||||||
 | 
					      if ($sel =~ /^a$/i) {
 | 
				
			||||||
 | 
					        delete $errors{InvalidName};
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      } elsif ($sel =~ /^c$/i) {
 | 
				
			||||||
 | 
					        $errors{InvalidName} = UVmessage::get("MENU_INVALIDNAME");
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      print UVmessage::get("MENU_NAME"), ": ";
 | 
				
			||||||
 | 
					      $voter_name = <STDIN>;
 | 
				
			||||||
 | 
					      chomp ($voter_name);
 | 
				
			||||||
 | 
					      $$name = $voter_name;
 | 
				
			||||||
 | 
					      push (@$set, 'Name');
 | 
				
			||||||
 | 
					      delete $errors{NoName};
 | 
				
			||||||
 | 
					      delete $errors{InvalidName};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $errors{InvalidName} = UVmessage::get("MENU_INVALIDNAME")
 | 
				
			||||||
 | 
					        unless ($voter_name =~ /$config{name_re}/);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    } elsif ($input eq '4') {
 | 
				
			||||||
 | 
					      # set votes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my $sel;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        print "[a] ", UVmessage::get("MENU_VOTES_OK"), "\n",
 | 
				
			||||||
 | 
					              "[b] ", UVmessage::get("MENU_VOTES_RESET"), "\n",
 | 
				
			||||||
 | 
					              "[c] ", UVmessage::get("MENU_VOTES_INVALID"), "\n",
 | 
				
			||||||
 | 
					              "[d] ", UVmessage::get("MENU_VOTES_CANCELLED"), "\n\n",
 | 
				
			||||||
 | 
					              UVmessage::get("MENU_PROMPT");
 | 
				
			||||||
 | 
					        $sel = <STDIN>;
 | 
				
			||||||
 | 
					      } until ($sel =~ /^[abcd]$/i);
 | 
				
			||||||
 | 
					      if ($sel =~ /^[ad]$/i) {
 | 
				
			||||||
 | 
					        delete $errors{NoVote};
 | 
				
			||||||
 | 
					        delete $errors{UnrecognizedVote};
 | 
				
			||||||
 | 
					        delete $errors{ViolatedRule};
 | 
				
			||||||
 | 
					        delete $errors{DuplicateVote};
 | 
				
			||||||
 | 
					        if ($sel =~ /^d$/i) {
 | 
				
			||||||
 | 
					          # cancelled vote: replace all votes with an A
 | 
				
			||||||
 | 
					          @$votes = split(//, 'A' x scalar @groups);
 | 
				
			||||||
 | 
					          push @$set, 'Stimmen';
 | 
				
			||||||
 | 
					          # some errors are irrelevant when cancelling a vote:
 | 
				
			||||||
 | 
					          delete $errors{InvalidName};
 | 
				
			||||||
 | 
					          delete $errors{NoName};
 | 
				
			||||||
 | 
					          delete $errors{InvalidBDSG};
 | 
				
			||||||
 | 
					          delete $errors{InvalidAddress};
 | 
				
			||||||
 | 
					          delete $errors{SuspiciousAccount};
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      } elsif ($sel =~ /^c$/i) {
 | 
				
			||||||
 | 
					        $errors{NoVote} = UVmessage::get("MENU_INVALIDVOTE");
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Set columns for Text::Wrap
 | 
				
			||||||
 | 
					      $columns = $config{rightmargin};
 | 
				
			||||||
 | 
					      print "\n", wrap('', '', UVmessage::get("MENU_VOTES_REENTER_ASK")), "\n\n";
 | 
				
			||||||
 | 
					      print UVmessage::get("MENU_VOTES_REENTER_LEGEND"), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (my $n=0; $n<@groups; $n++) {
 | 
				
			||||||
 | 
					        my $voteinput = "";
 | 
				
			||||||
 | 
					        $votes->[$n] ||= 'E';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # repeat while invalid character entered
 | 
				
			||||||
 | 
					        while (!($voteinput =~ /^[JNE]$/)) {
 | 
				
			||||||
 | 
					          my $invalid = $#groups ? 0 : 1;
 | 
				
			||||||
 | 
					          print UVmessage::get("MENU_VOTES_REENTER", (GROUP => $groups[$n]));
 | 
				
			||||||
 | 
					          $voteinput = <STDIN>;
 | 
				
			||||||
 | 
					          chomp $voteinput;
 | 
				
			||||||
 | 
					          $voteinput ||= $votes->[$n];
 | 
				
			||||||
 | 
					          $voteinput =~ tr/jne/JNE/;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # valid input, save new votes
 | 
				
			||||||
 | 
					        $newvotes[$n] = $voteinput;
 | 
				
			||||||
 | 
					      } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print "\n\n";
 | 
				
			||||||
 | 
					      my $oldvotes = UVmessage::get("MENU_VOTES_REENTER_OLD");
 | 
				
			||||||
 | 
					      my $newvotes = UVmessage::get("MENU_VOTES_REENTER_NEW");
 | 
				
			||||||
 | 
					      my $oldlen = length($oldvotes);
 | 
				
			||||||
 | 
					      my $newlen = length($newvotes);
 | 
				
			||||||
 | 
					      my $maxlen = 1 + (($newlen>$oldlen) ? $newlen : $oldlen);
 | 
				
			||||||
 | 
					      print $oldvotes, ' ' x ($maxlen - length($oldvotes)), @$votes, "\n",
 | 
				
			||||||
 | 
					            $newvotes, ' ' x ($maxlen - length($newvotes)), @newvotes, "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        print "[a] ", UVmessage::get("MENU_VOTES_REENTER_ACK"), "    ",
 | 
				
			||||||
 | 
					              "[b] ", UVmessage::get("MENU_VOTES_REENTER_NACK"), "\n\n", 
 | 
				
			||||||
 | 
					               UVmessage::get("MENU_PROMPT");
 | 
				
			||||||
 | 
					        $sel = <STDIN>;
 | 
				
			||||||
 | 
					      } until ($sel =~ /^[ab]$/i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      next if ($sel =~ /^b$/i);
 | 
				
			||||||
 | 
					      @$votes = @newvotes;
 | 
				
			||||||
 | 
					      push @$set, 'Stimmen';
 | 
				
			||||||
 | 
					      delete $errors{UnrecognizedVote};
 | 
				
			||||||
 | 
					      delete $errors{DuplicateVote};
 | 
				
			||||||
 | 
					      delete $errors{NoVote};
 | 
				
			||||||
 | 
					      delete $errors{ViolatedRule};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (my $rule = UVrules::rule_check($votes)) {
 | 
				
			||||||
 | 
					        $errors{ViolatedRule} = UVmessage::get("MENU_VIOLATEDRULE", (RULE => "#$rule"));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif ($input eq '5' && $config{personal}) {
 | 
				
			||||||
 | 
					      print "\n", UVmessage::get("MENU_BALLOT_ID"), ": ";
 | 
				
			||||||
 | 
					      $$ballot_id = <STDIN>;
 | 
				
			||||||
 | 
					      chomp ($$ballot_id);
 | 
				
			||||||
 | 
					      push (@$set, 'Kennung');
 | 
				
			||||||
 | 
					      check_ballotid(\%errors, \$voter_addr, $ballot_id, \%ids);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif ($input eq '6' && $config{bdsg}) {
 | 
				
			||||||
 | 
					      my $sel;
 | 
				
			||||||
 | 
					      do {
 | 
				
			||||||
 | 
					        print "[a] ", UVmessage::get("MENU_BDSG_ACCEPTED"), "\n",
 | 
				
			||||||
 | 
					              "[b] ", UVmessage::get("MENU_BDSG_DECLINED"), "\n\n",
 | 
				
			||||||
 | 
					              UVmessage::get("MENU_PROMPT");
 | 
				
			||||||
 | 
					        $sel = <STDIN>;
 | 
				
			||||||
 | 
					      } until ($sel =~ /^[ab]$/i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ($sel =~ /^a$/i) {
 | 
				
			||||||
 | 
					        delete $errors{InvalidBDSG};
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $errors{InvalidBDSG} = UVmessage::get("MENU_INVALIDBDSG");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif ($input =~ /^i$/i) {
 | 
				
			||||||
 | 
					      my $ignore = UVmessage::get("MENU_IGNORE_STRING");
 | 
				
			||||||
 | 
					      # Set columns for Text::Wrap
 | 
				
			||||||
 | 
					      $columns = $config{rightmargin};
 | 
				
			||||||
 | 
					      print wrap('', '', UVmessage::get("MENU_IGNORE_WARNING",
 | 
				
			||||||
 | 
					                                        (MENU_IGNORE_STRING => $ignore)
 | 
				
			||||||
 | 
					                                       ));
 | 
				
			||||||
 | 
					      if (<STDIN> eq "$ignore\n") {
 | 
				
			||||||
 | 
					        print "\n";
 | 
				
			||||||
 | 
					        return "i";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } elsif ($input =~ /^w$/i) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (keys %errors) {
 | 
				
			||||||
 | 
					        if ((keys %errors)==1 && $errors{UnrecognizedVote}) {
 | 
				
			||||||
 | 
					          # unrecognized vote lines aren't errors if votetaker
 | 
				
			||||||
 | 
					          # did not change them
 | 
				
			||||||
 | 
					          @$errors = ();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          # Set columns for Text::Wrap
 | 
				
			||||||
 | 
					          $columns = $config{rightmargin};
 | 
				
			||||||
 | 
					          @$errors = keys %errors;
 | 
				
			||||||
 | 
					          my $warning = ' ' . UVmessage::get("MENU_ERROR_WARNING") . ' ';
 | 
				
			||||||
 | 
					          my $length = length($warning);
 | 
				
			||||||
 | 
					          print "\n", '*' x (($config{rightmargin}-$length)/2), $warning,
 | 
				
			||||||
 | 
					                '*' x (($config{rightmargin}-$length)/2), "\n\n",
 | 
				
			||||||
 | 
					                wrap('', '', UVmessage::get("MENU_ERROR_TEXT")), "\n\n",
 | 
				
			||||||
 | 
					                '*' x $config{rightmargin}, "\n\n",
 | 
				
			||||||
 | 
					                UVmessage::get("MENU_ERROR_GETKEY");
 | 
				
			||||||
 | 
					          my $input = <STDIN>;
 | 
				
			||||||
 | 
					          next if ($input !~ /^y$/i);
 | 
				
			||||||
 | 
					          print "\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        @$errors = ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      system($config{clearcmd});
 | 
				
			||||||
 | 
					      print "\n", UVmessage::get("MENU_PROCESSING"), "\n";
 | 
				
			||||||
 | 
					      return "w";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sub check_ballotid {
 | 
				
			||||||
 | 
					    my ($errors, $voter_addr, $ballot_id, $ids) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0 unless ($config{personal});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete $errors->{NoBallotID};
 | 
				
			||||||
 | 
					    delete $errors->{WrongBallotID};
 | 
				
			||||||
 | 
					    delete $errors->{AddressNotRegistered};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($$ballot_id) {
 | 
				
			||||||
 | 
					      if ($ids->{$$voter_addr}) {
 | 
				
			||||||
 | 
					        if ($ids->{$$voter_addr} ne $$ballot_id) {
 | 
				
			||||||
 | 
					          # ballot id incorrect
 | 
				
			||||||
 | 
					          $errors->{WrongBallotID} = UVmessage::get("MENU_WRONGBALLOTID");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $errors->{AddressNotRegistered} = UVmessage::get("MENU_ADDRESSNOTREGISTERED");
 | 
				
			||||||
 | 
					      } 
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $errors->{NoBallotID} = UVmessage::get("MENU_NOBALLOTID");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Menu for sorting out duplicate votings manually                            #
 | 
				
			||||||
 | 
					# Parameters: References to hashes with the paragraphs from the result file  #
 | 
				
			||||||
 | 
					#             and the default value                                          #
 | 
				
			||||||
 | 
					# Return value: selected menu item (1, 2 or 0)                               #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub dup_choice {
 | 
				
			||||||
 | 
					  my ($vote1, $vote2, $default) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print STDERR "\n", UVmessage::get("MENU_DUP_VOTE"), "\n\n";
 | 
				
			||||||
 | 
					  print STDERR UVmessage::get("MENU_DUP_FIRST"), "\n";
 | 
				
			||||||
 | 
					  print STDERR "A: $vote1->{A}\n";
 | 
				
			||||||
 | 
					  print STDERR "N: $vote1->{N}\n";
 | 
				
			||||||
 | 
					  print STDERR "D: $vote1->{D}\n";
 | 
				
			||||||
 | 
					  print STDERR "K: $vote1->{K}\n";
 | 
				
			||||||
 | 
					  print STDERR "S: $vote1->{S}\n\n";
 | 
				
			||||||
 | 
					  print STDERR UVmessage::get("MENU_DUP_SECOND"), "\n";
 | 
				
			||||||
 | 
					  print STDERR "A: $vote2->{A}\n";
 | 
				
			||||||
 | 
					  print STDERR "N: $vote2->{N}\n";
 | 
				
			||||||
 | 
					  print STDERR "D: $vote2->{D}\n";
 | 
				
			||||||
 | 
					  print STDERR "K: $vote2->{K}\n";
 | 
				
			||||||
 | 
					  print STDERR "S: $vote2->{S}\n\n";
 | 
				
			||||||
 | 
					  print STDERR "1: ", UVmessage::get("MENU_DUP_DELFIRST"), "\n",
 | 
				
			||||||
 | 
					               "2: ", UVmessage::get("MENU_DUP_DELSECOND"), "\n",
 | 
				
			||||||
 | 
					               "0: ", UVmessage::get("MENU_DUP_DELNONE"), "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    print STDERR UVmessage::get("MENU_PROMPT"), "[$default] ";
 | 
				
			||||||
 | 
					    $input = <STDIN>;
 | 
				
			||||||
 | 
					    chomp $input;
 | 
				
			||||||
 | 
					  } until ($input eq '' || ($input >= 0 && $input<3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $input || $default;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
							
								
								
									
										32
									
								
								UVmessage.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								UVmessage.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					# UVmessages: parses resource strings and substitutes variables
 | 
				
			||||||
 | 
					# Used by all components
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package UVmessage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use vars qw(@ISA @EXPORT_OK $VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require Exporter;
 | 
				
			||||||
 | 
					@ISA = qw(Exporter);
 | 
				
			||||||
 | 
					@EXPORT_OK = qw(get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Module version
 | 
				
			||||||
 | 
					$VERSION = "0.1";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub get {
 | 
				
			||||||
 | 
					  my ($key, %param) = @_;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  my $string = $UVconfig::messages{$key} || return '';
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  while ($string =~ m/\$\{([A-Za-z0-9_-]+)\}/) {
 | 
				
			||||||
 | 
					    my $skey = $1;
 | 
				
			||||||
 | 
					    my $sval = $param{$skey};
 | 
				
			||||||
 | 
					    $sval = '' unless defined($sval);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    $string =~ s/\$\{$skey\}/$sval/g;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  return $string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
							
								
								
									
										225
									
								
								UVreadmail.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								UVreadmail.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,225 @@
 | 
				
			||||||
 | 
					# UVreadmail: functions for reading and processing mailfiles
 | 
				
			||||||
 | 
					# Used by uvvote.pl, uvcfv.pl, uvbounce.pl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package UVreadmail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					use MIME::QuotedPrint;
 | 
				
			||||||
 | 
					use MIME::Base64;
 | 
				
			||||||
 | 
					use MIME::Parser;
 | 
				
			||||||
 | 
					use POSIX qw(strftime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use vars qw($VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Module version
 | 
				
			||||||
 | 
					$VERSION = "0.11";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub process {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # $filename: file containing bounces or (if POP3 is enabled) where
 | 
				
			||||||
 | 
					  #            mails should be saved
 | 
				
			||||||
 | 
					  # $callsub:  reference to a sub which should be called for each mail
 | 
				
			||||||
 | 
					  # $caller:   0 = uvvote.pl, 1 = uvcfv.pl, 2 = uvbounce.pl
 | 
				
			||||||
 | 
					  #            3 = uvbounce.pl but POP3 disabled (overrides $config{pop3}
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my ($filename, $callsub, $caller) = @_;
 | 
				
			||||||
 | 
					  my ($voter_addr, $voter_name, $body);
 | 
				
			||||||
 | 
					  my $count = 0;
 | 
				
			||||||
 | 
					  my ($pop3server, $pop3user, $pop3pass, $pop3delete, $pop3uidlcache);
 | 
				
			||||||
 | 
					  my @mails = ();
 | 
				
			||||||
 | 
					  $caller ||= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($config{pop3} && $caller<3) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($caller == 1) {
 | 
				
			||||||
 | 
					      # Ballot request (personal = 1 set in usevote.cfg) from uvcfv.pl
 | 
				
			||||||
 | 
					      $pop3server = $config{pop3server_req} . ':' . $config{pop3port_req};
 | 
				
			||||||
 | 
					      $pop3user = $config{pop3user_req};
 | 
				
			||||||
 | 
					      $pop3pass = $config{pop3pass_req};
 | 
				
			||||||
 | 
					      $pop3delete = $config{pop3delete_req};
 | 
				
			||||||
 | 
					      $pop3uidlcache = $config{pop3uidlcache_req};
 | 
				
			||||||
 | 
					    } elsif ($caller == 2) {
 | 
				
			||||||
 | 
					      # called from uvbounce.pl
 | 
				
			||||||
 | 
					      $pop3server = $config{pop3server_bounce} . ':' . $config{pop3port_bounce};
 | 
				
			||||||
 | 
					      $pop3user = $config{pop3user_bounce};
 | 
				
			||||||
 | 
					      $pop3pass = $config{pop3pass_bounce};
 | 
				
			||||||
 | 
					      $pop3delete = $config{pop3delete_bounce};
 | 
				
			||||||
 | 
					      $pop3uidlcache = $config{pop3uidlcache_bounce};
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $pop3server = $config{pop3server} . ':' . $config{pop3port};
 | 
				
			||||||
 | 
					      $pop3user = $config{pop3user};
 | 
				
			||||||
 | 
					      $pop3pass = $config{pop3pass};
 | 
				
			||||||
 | 
					      $pop3delete = $config{pop3delete};
 | 
				
			||||||
 | 
					      $pop3uidlcache = $config{pop3uidlcache};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # read list of seen mails (UIDLs)
 | 
				
			||||||
 | 
					    my %uidls = ();  # hash for quick searching
 | 
				
			||||||
 | 
					    my @uidls = ();  # array to preserve order
 | 
				
			||||||
 | 
					    my $cacheexist = 1;
 | 
				
			||||||
 | 
					    open (UIDLCACHE, "<$pop3uidlcache") or $cacheexist = 0;
 | 
				
			||||||
 | 
					    if ($cacheexist) {
 | 
				
			||||||
 | 
					      while (my $uidl = <UIDLCACHE>) {
 | 
				
			||||||
 | 
					        chomp ($uidl);
 | 
				
			||||||
 | 
					        $uidls{$uidl} = 1;
 | 
				
			||||||
 | 
					        push (@uidls, $uidl);
 | 
				
			||||||
 | 
					      }     
 | 
				
			||||||
 | 
					      close (UIDLCACHE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print UVmessage::get("READMAIL_STATUS"), "\n" unless ($caller == 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # open POP3 connection and get new mails
 | 
				
			||||||
 | 
					    use Net::POP3;
 | 
				
			||||||
 | 
					    my $pop = Net::POP3->new($pop3server)
 | 
				
			||||||
 | 
					      or die UVmessage::get("READMAIL_NOCONNECTION") . "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $mailcount = $pop->login($pop3user, $pop3pass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    die UVmessage::get("READMAIL_NOLOGIN") . "\n\n" unless ($mailcount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (my $n=1; $n<=$mailcount; $n++) {
 | 
				
			||||||
 | 
					      my $uidl = $pop->uidl($n);
 | 
				
			||||||
 | 
					      if ($uidl) {
 | 
				
			||||||
 | 
					        next if ($uidls{$uidl});
 | 
				
			||||||
 | 
					        $uidls{$uidl} = 1;
 | 
				
			||||||
 | 
					        push (@uidls, $uidl);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      my $mailref = $pop->get($n)
 | 
				
			||||||
 | 
					         or print STDERR UVmessage::get("READMAIL_GET_PROBLEM", (NR => $n)) . "\n";
 | 
				
			||||||
 | 
					      my $mail = join ('', @$mailref);
 | 
				
			||||||
 | 
					      my $fromline = 'From ';
 | 
				
			||||||
 | 
					      if ($mail =~ /From: .*?<(.+?)>/) {
 | 
				
			||||||
 | 
					        $fromline .= $1;
 | 
				
			||||||
 | 
					      } elsif ($mail =~ /From:\s+?(\S+?\@\S+?)\s/) {
 | 
				
			||||||
 | 
					        $fromline .= $1;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $fromline .= 'foo@bar.invalid';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      $fromline .= ' ' . strftime ('%a %b %d %H:%M:%S %Y', localtime) . "\n";
 | 
				
			||||||
 | 
					      push (@mails, $fromline . $mail);
 | 
				
			||||||
 | 
					      if ($pop3delete) {
 | 
				
			||||||
 | 
					        $pop->delete($n)
 | 
				
			||||||
 | 
					          or print STDERR UVmessage::get("READMAIL_DEL_PROBLEM", (NR => $n)) . "\n";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # save UIDLs
 | 
				
			||||||
 | 
					    my $uidlerr = 0;
 | 
				
			||||||
 | 
					    open (UIDLCACHE, ">$pop3uidlcache") or $uidlerr = 1;
 | 
				
			||||||
 | 
					    if ($uidlerr) {
 | 
				
			||||||
 | 
					      print STDERR UVmessage::get("READMAIL_UIDL_PROBLEM") . "\n";
 | 
				
			||||||
 | 
					      print STDERR UVmessage::get("READMAIL_UIDL_PROBLEM2") . "\n";
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      print UIDLCACHE join("\n", @uidls);
 | 
				
			||||||
 | 
					      close (UIDLCACHE) or print STDERR UVmessage::get("READMAIL_UIDL_CLOSE") . "\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # make archive of all mails
 | 
				
			||||||
 | 
					    my $fileproblem = 0;
 | 
				
			||||||
 | 
					    open (VOTES, ">$filename") or $fileproblem = 1;
 | 
				
			||||||
 | 
					    if ($fileproblem) {
 | 
				
			||||||
 | 
					      print STDERR UVmessage::get("READMAIL_ARCHIVE_PROBLEM",
 | 
				
			||||||
 | 
					                   (FILE => $filename)) . "\n";
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      print VOTES join ("\n", @mails);
 | 
				
			||||||
 | 
					      close (VOTES)
 | 
				
			||||||
 | 
					        or print STDERR UVmessage::get("READMAIL_ARCHIVE_CLOSE",
 | 
				
			||||||
 | 
					                        (FILE => $filename)) . "\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $pop->quit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # open mail file
 | 
				
			||||||
 | 
					    open(VOTES, "<$filename")
 | 
				
			||||||
 | 
					        or die UVmessage::get("READMAIL_NOMAILFILE", (FILE => $filename)) . "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # read all mails
 | 
				
			||||||
 | 
					    my $i = 0;
 | 
				
			||||||
 | 
					    while (<VOTES>) {
 | 
				
			||||||
 | 
					      if (/$config{mailstart}/) {
 | 
				
			||||||
 | 
					        $i++;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      $mails[$i] = ($mails[$i] || "") . $_;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # close mail file
 | 
				
			||||||
 | 
					    close(VOTES);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $mail (@mails) {
 | 
				
			||||||
 | 
					    next unless $mail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # split mail into array and remove first line (from line)
 | 
				
			||||||
 | 
					    my @mail = split(/\n/, $mail);
 | 
				
			||||||
 | 
					    shift (@mail) if ($mail[0] =~ /^From /);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # generate MIME-Parser object for the mail
 | 
				
			||||||
 | 
					    my $parser = new MIME::Parser;
 | 
				
			||||||
 | 
					    # headers are to be decoded
 | 
				
			||||||
 | 
					    $parser->decode_headers(1);
 | 
				
			||||||
 | 
					    # don't write into file
 | 
				
			||||||
 | 
					    $parser->output_to_core(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # read mail
 | 
				
			||||||
 | 
					    my $entity = $parser->parse_data(join("\n", @mail));
 | 
				
			||||||
 | 
					    my $head = $entity->head;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # extract address and name
 | 
				
			||||||
 | 
					    my $from = $head->get('From') || '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($from =~ /\s*([^<]\S+\@\S+[^>]) \((.+)\)/) {
 | 
				
			||||||
 | 
					      ($voter_addr, $voter_name) = ($1, $2);
 | 
				
			||||||
 | 
					    } elsif ($from =~ /\s*\"?([^\"]+)\"?\s*<(\S+\@\S+)>/) {
 | 
				
			||||||
 | 
					      ($voter_name, $voter_addr) = ($1, $2);
 | 
				
			||||||
 | 
					      $voter_name =~ s/\s+$//;  # kill spaces at the end
 | 
				
			||||||
 | 
					    } elsif ($from =~ /\s*<?(\S+\@[^\s>]+)>?[^\(\)]*/) {
 | 
				
			||||||
 | 
					      ($voter_addr, $voter_name) = ($1, '');
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      # initialize with empty value
 | 
				
			||||||
 | 
					      $voter_addr = '';
 | 
				
			||||||
 | 
					      $voter_name = '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # look at reply-to?
 | 
				
			||||||
 | 
					    if ($config{replyto}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my $replyto = Mail::Field->new('Reply-To', $head->get('Reply-To'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Address in Reply-To?
 | 
				
			||||||
 | 
					      ($voter_addr) = $replyto->addresses() if ($replyto->addresses());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Name in reply-to?
 | 
				
			||||||
 | 
					      if ($replyto->names()) {
 | 
				
			||||||
 | 
					         my ($nametmp) = $replyto->names();
 | 
				
			||||||
 | 
					         $voter_name = $nametmp unless ($nametmp =~ /^\s*$/);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # decode body
 | 
				
			||||||
 | 
					    my $encoding = $head->get('Content-Transfer-Encoding') || '';
 | 
				
			||||||
 | 
					    if ($encoding =~ /quoted-printable/i) {
 | 
				
			||||||
 | 
					      $body = decode_qp($entity->stringify_body);
 | 
				
			||||||
 | 
					    } elsif ($encoding =~ /base64/i) {
 | 
				
			||||||
 | 
					      $body = decode_base64($entity->stringify_body);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $body = $entity->stringify_body;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $h_date = $head->get('Date') || '';
 | 
				
			||||||
 | 
					    chomp $h_date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # call referred sub and increase counter
 | 
				
			||||||
 | 
					    &$callsub($voter_addr, $voter_name, $h_date, $entity, \$body);
 | 
				
			||||||
 | 
					    $count++;
 | 
				
			||||||
 | 
					  } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
							
								
								
									
										409
									
								
								UVrules.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										409
									
								
								UVrules.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,409 @@
 | 
				
			||||||
 | 
					# UVrules: Module with rule functions for usevote
 | 
				
			||||||
 | 
					# Used by uvvote.pl, UVconfig.pm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package UVrules;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use vars qw (@ISA @EXPORT $VERSION @rules);
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					require Exporter;
 | 
				
			||||||
 | 
					@ISA = qw(Exporter);
 | 
				
			||||||
 | 
					@EXPORT = qw(@rules);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					# Module version
 | 
				
			||||||
 | 
					$VERSION = "0.3"; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ---------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Erlaeuterung zur Regelpruefung (to be translated)
 | 
				
			||||||
 | 
					# ---------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Um Stimmen mit multiplen Abstimmungspunkten auf ihre Sinnfaelligkeit 
 | 
				
			||||||
 | 
					# pruefen zu koennen, koennen in Usevote verschiedenste Regeln
 | 
				
			||||||
 | 
					# fuer solche Pruefungen definiert werden. 
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Die Regeln bestehen aus zwei Teilen. Einer IF-Klausel und einer THEN-
 | 
				
			||||||
 | 
					# Klausel. Die IF-Klausel bestimmt, ob die Stimme mit der THEN-Klausel
 | 
				
			||||||
 | 
					# verglichen werden soll. Passt sie auf diese, ist die Stimme in Ordnung,
 | 
				
			||||||
 | 
					# wenn nicht liegt ein Fehler vor.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Ein kleines Beispiel: "IF S.. THEN .SS"
 | 
				
			||||||
 | 
					# Wenn beim ersten Punkt mit Ja oder Nein gestimmt wurde, dann muss
 | 
				
			||||||
 | 
					# bei den anderen beiden Punkten auch ein Ja oder Nein vorliegen.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Die Stimmabgabe JNE wuerde also gegen die obige Regel verstossen,
 | 
				
			||||||
 | 
					# JJN nicht. EEJ wuerde ebenfalls gueltig sein, da die Regel nicht unter
 | 
				
			||||||
 | 
					# die IF-Klausel faellt und somit keine Ueberpruefung der THEN-Klausel
 | 
				
			||||||
 | 
					# erfolgt.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# ---------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Implementierung
 | 
				
			||||||
 | 
					# ---------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Um eine moeglichst einfache Ueberpruefung der Stimmen vorzunehmen,
 | 
				
			||||||
 | 
					# bietet es sich an, aus den beiden Klauseln regulaere Ausdruecke zu
 | 
				
			||||||
 | 
					# generieren. Diese wuerden dann auf die Stimme angewandt werden.
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# Bei der Umwandlung in regulaere Audruecke kommt uns die Notation
 | 
				
			||||||
 | 
					# der Regeln bereits entgegen. So kann der Punkt als beliebige Stimme
 | 
				
			||||||
 | 
					# beibehalten werden. Die grossen Buchstaben bleiben ebenfalls bis
 | 
				
			||||||
 | 
					# auf S erhalten, da die zu pruefenden Stimmen aus den Buchstaben
 | 
				
			||||||
 | 
					# 'JNE' bestehen.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# So muessen wir zur Ueberpruefung von direkten Stimmen nur 'S' in
 | 
				
			||||||
 | 
					# eine Klasse mit [JN] und I in eine Klasse mit [EN] umwandeln.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 'J..' => 'J..', 'NNE' => 'NNE', 'S..' => '[JN]..'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Bei den indirekten Stimmabgaben wird es schon schwieriger. Hier 
 | 
				
			||||||
 | 
					# muessten alle Moeglichkeiten eines Strings gebaut werden, um zu
 | 
				
			||||||
 | 
					# testen ob mindestens eine Version matcht.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# '.jjj' => '.(j..|.j.|..j)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Je komplexer die Regeln, um so mehr Moeglichkeiten muessten
 | 
				
			||||||
 | 
					# konstruiert werden, um einen geschlossenen regulaeren Ausdruck
 | 
				
			||||||
 | 
					# zu erhalten.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Wir koennen den Regex aber auch einfach aufbauen, in dem wir
 | 
				
			||||||
 | 
					# nicht alle Faelle betrachten die moeglich sind, sondern nur die
 | 
				
			||||||
 | 
					# Faelle die nicht erlaubt sind. 
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# D.h. soll an einer Stelle ein Ja stehen, erlauben wir dort
 | 
				
			||||||
 | 
					# nur Nein und Enthaltungen. Passt eine Stimme auf diesen Regex,
 | 
				
			||||||
 | 
					# kann sie unmoeglich die Vorgabe enthalten.
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# 'nnnn' => '[JE][JE][JE][JE]'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Besteht eine Stimme also nur aus Ja und Enthaltung, wissen wir
 | 
				
			||||||
 | 
					# das kein einziges Nein enthalten seien kann. Die Stimme passt
 | 
				
			||||||
 | 
					# also nicht auf unser Muster.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Tritt hingegen nur ein einziges J auf, passt der regulaere Ausdruck
 | 
				
			||||||
 | 
					# nicht mehr, und wir wissen, dass die Stimme die Regel erfuellt.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Wie wir sehen koennen, ist der negative Ausdruck leichter zu
 | 
				
			||||||
 | 
					# bilden als der positive. 
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Da eine Stimme nun sowohl aus direkten, als auch indirekten
 | 
				
			||||||
 | 
					# Stimmen bestehen kann (z.B. 'Jnnn..') muessen wir die Stimme
 | 
				
			||||||
 | 
					# zerlegen. Wir bilden einen positiven Regex fuer die Grossbuch-
 | 
				
			||||||
 | 
					# staben und einen negativen Regex fuer die kleinen.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Passt eine Stimme dann auf den positiven Regex und nicht auf
 | 
				
			||||||
 | 
					# den negativen Regex, so entspricht sie der urspruenglichen
 | 
				
			||||||
 | 
					# Regel.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Ein Beispiel: 'Sss..' (Der erste Punkt und der zweite oder dritte
 | 
				
			||||||
 | 
					# Punkt muessen ein Ja oder Nein sein.)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# positiver Regex: '[JN]...'	muss erfuellt werden
 | 
				
			||||||
 | 
					# negativer Regex: '.EE.'	darf nicht erfuellt werden
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# JJNN => positiv matcht => negativ matcht nicht => Regel erfuellt
 | 
				
			||||||
 | 
					# ENJE => positiv matcht nicht => Regel nicht erfuellt
 | 
				
			||||||
 | 
					# NEEJ => positiv matcht => negativ matcht => Regel nicht erfuellt
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Mit Hilfe dieser Technik, lassen sich einfach Regex bilden, die
 | 
				
			||||||
 | 
					# ebenso einfach ueberprueft werden koennen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Read usevote.rul and check rules for correct syntax                        #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					sub read_rulefile {
 | 
				
			||||||
 | 
					  @rules = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  open (RULES, "<$config{rulefile}")
 | 
				
			||||||
 | 
					    or die UVmessage::get("RULES_ERROPENFILE", (FILE => $config{rulefile})) . "\n\n";
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  while (<RULES>) {
 | 
				
			||||||
 | 
					    chomp;
 | 
				
			||||||
 | 
					    s/#.*$//;  # delete comments
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    # does line match correct if-then syntax?
 | 
				
			||||||
 | 
					    if (/^\s*if\s+(\S+)\s+then\s+(\S+)\s*$/) {
 | 
				
			||||||
 | 
					      my $if   = $1;
 | 
				
			||||||
 | 
					      my $then = $2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # $num contains the rule's array index
 | 
				
			||||||
 | 
					      my $num = @rules;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      # check for correct length of condition
 | 
				
			||||||
 | 
					      my $errortext;
 | 
				
			||||||
 | 
					      if (length($if) < @groups) {
 | 
				
			||||||
 | 
					        $errortext = UVmessage::get("RULES_TOOSHORT", (NUM=>$num+1, TYPE=>"if"));
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      } elsif (length($if) > @groups) {
 | 
				
			||||||
 | 
					        $errortext = UVmessage::get("RULES_TOOLONG", (NUM=>$num+1, TYPE=>"if"));
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      } elsif (length($then) < @groups) {
 | 
				
			||||||
 | 
					        $errortext = UVmessage::get("RULES_TOOSHORT", (NUM=>$num+1, TYPE=>"then"));
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      } elsif (length($then) > @groups) {
 | 
				
			||||||
 | 
					        $errortext = UVmessage::get("RULES_TOOLONG", (NUM=>$num+1, TYPE=>"then"));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      die $errortext . ": $_\n\n" if ($errortext);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      # check for correct characters in conditions
 | 
				
			||||||
 | 
					      if ($if !~ /^[JjNnEeSsHhIi\.]+$/) {
 | 
				
			||||||
 | 
					        die UVmessage::get ("RULES_INVCHARS", (NUM=>$num+1, TYPE=>"if")) . ": $if\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      } elsif ($then !~ /^[JjNnEeSsHhIi\.]+$/) {
 | 
				
			||||||
 | 
					        die UVmessage::get ("RULES_INVCHARS",
 | 
				
			||||||
 | 
					                            (NUM=>$num+1, TYPE=>"if")) . ": $then\n\n";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      # Zur Speicherung der Regeln (to be translated):
 | 
				
			||||||
 | 
					      # - if_compl und then_compl sind die kompletten Bedingungen als Strings,
 | 
				
			||||||
 | 
					      #   werden fuer die Sprachausgabe der Regeln benoetigt
 | 
				
			||||||
 | 
					      # - zusaetzlich werden der if- und then-Teil fuer die einfachere
 | 
				
			||||||
 | 
					      #   Verarbeitung in zwei Teile gesplittet: Eine Positiv-Regex, die auf
 | 
				
			||||||
 | 
					      #   die Grossbuchstaben (explizite Forderungen, UND-Verknuepfungen)
 | 
				
			||||||
 | 
					      #   matched, und eine Negativ-Regex, die bei den Kleinbuchstaben
 | 
				
			||||||
 | 
					      #   (optionale Felder, ODER-Verknuepfungen) verwendet wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my %rule = ( if_compl   => $if,
 | 
				
			||||||
 | 
					                   if_pos     => make_regex_pos($if),
 | 
				
			||||||
 | 
					                   if_neg     => make_regex_neg($if),
 | 
				
			||||||
 | 
					                   then_compl => $then,
 | 
				
			||||||
 | 
					                   then_pos   => make_regex_pos($then),
 | 
				
			||||||
 | 
					                   then_neg   => make_regex_neg($then) );
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					      push (@rules, \%rule);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Generates a RegEx for positive matching of the rules                       #
 | 
				
			||||||
 | 
					#                                                                            #
 | 
				
			||||||
 | 
					# All lower case characters are replaced with dots, as they are to be        #
 | 
				
			||||||
 | 
					# matched by the negativ RegEx. Furthermore the symbol S is replaced by [JN] #
 | 
				
			||||||
 | 
					# and I is replaced by [EN] (for use in combined votings when only one       #
 | 
				
			||||||
 | 
					# option may be accepted and the others must be rejected or abstained.       #
 | 
				
			||||||
 | 
					# As a result we have a regular expression that can be matched against the   #
 | 
				
			||||||
 | 
					# received votes.                                                            #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					sub make_regex_pos {
 | 
				
			||||||
 | 
					  my $pat = $_[0];
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  $pat =~ s/[hijens]/./g;
 | 
				
			||||||
 | 
					  $pat =~ s/S/[JN]/g;
 | 
				
			||||||
 | 
					  $pat =~ s/H/[EJ]/g;
 | 
				
			||||||
 | 
					  $pat =~ s/I/[EN]/g;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  return $pat;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Generates a RegEx for negative matching of the rules                       #
 | 
				
			||||||
 | 
					#                                                                            #
 | 
				
			||||||
 | 
					# All upper case characters are replaced with dots, as they are to be        #
 | 
				
			||||||
 | 
					# matched by the positiv RegEx. If lower case characters are found the       #
 | 
				
			||||||
 | 
					# condition is reversed, so that we are able to match votes *not*            #
 | 
				
			||||||
 | 
					# corresponding to this rule                                                 #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					sub make_regex_neg {
 | 
				
			||||||
 | 
					  my $pat = $_[0];
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  # upper case characters are replaced with dots
 | 
				
			||||||
 | 
					  # (are covered by make_regex_pos)
 | 
				
			||||||
 | 
					  $pat =~ s/[HIJENS]/./g;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  # reverse lower case characters
 | 
				
			||||||
 | 
					  $pat =~ s/j/[NE]/g;
 | 
				
			||||||
 | 
					  $pat =~ s/n/[JE]/g;
 | 
				
			||||||
 | 
					  $pat =~ s/e/[JN]/g;
 | 
				
			||||||
 | 
					  $pat =~ s/s/E/g;
 | 
				
			||||||
 | 
					  $pat =~ s/h/N/g;
 | 
				
			||||||
 | 
					  $pat =~ s/i/J/g;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  # If the string contained only upper case characters they are now all
 | 
				
			||||||
 | 
					  # replaced with dots and the RegEx would match everything, i.e. declare
 | 
				
			||||||
 | 
					  # every vote as invalid. In this case an empty pattern is returned.
 | 
				
			||||||
 | 
					  $pat =~ s/^\.+$//;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  return $pat;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Check a voting for rule compliance                                         #
 | 
				
			||||||
 | 
					# Parameters: Votes (Reference to Array)                                     #
 | 
				
			||||||
 | 
					# Return value: Number of violated rule or 0 (everything OK)                 #
 | 
				
			||||||
 | 
					# (Internally rules are saved with indexes starting at 0)                    #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub rule_check {
 | 
				
			||||||
 | 
					  my ($voteref) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Turn array reference into a string
 | 
				
			||||||
 | 
					  my $vote = join ('', @$voteref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # For compliance with the rules every rule has to be matched against the
 | 
				
			||||||
 | 
					  # the vote. If the IF clause matches but not the THEN clause the vote is
 | 
				
			||||||
 | 
					  # invalid and the rule number is returned.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (my $n = 0; $n < @rules; $n++) {
 | 
				
			||||||
 | 
					    return $n+1 if ($vote =~ m/^$rules[$n]->{if_pos}$/ &&
 | 
				
			||||||
 | 
					                    $vote !~ m/^$rules[$n]->{if_neg}$/ &&
 | 
				
			||||||
 | 
					                not($vote =~ m/^$rules[$n]->{then_pos}$/ &&
 | 
				
			||||||
 | 
					                    $vote !~ m/^$rules[$n]->{then_neg}$/ ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print rules in human readable format                                       #
 | 
				
			||||||
 | 
					# Parameter: rule number                                                     #
 | 
				
			||||||
 | 
					# Return value: rule text                                                    #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					sub rule_print {
 | 
				
			||||||
 | 
					  my ($n) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $and = UVmessage::get ("RULES_AND");
 | 
				
			||||||
 | 
					  my $or = UVmessage::get ("RULES_OR");
 | 
				
			||||||
 | 
					  my $yes = UVmessage::get ("RULES_YES");
 | 
				
			||||||
 | 
					  my $no = UVmessage::get ("RULES_NO");
 | 
				
			||||||
 | 
					  my $abst = UVmessage::get ("RULES_ABSTAIN");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $n++;
 | 
				
			||||||
 | 
					  my $text = UVmessage::get ("RULES_RULE") . " #$n:\n";
 | 
				
			||||||
 | 
					  $text .= "  " . UVmessage::get ("RULES_IF") . "\n";
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  my @rule = split (//, $rules[$n-1]->{if_compl});
 | 
				
			||||||
 | 
					  my $firstrun = 1;
 | 
				
			||||||
 | 
					  my $fill = "";
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  for (my $i=0; $i<@rule; $i++) {
 | 
				
			||||||
 | 
					    my $text1 = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($rule[$i] eq 'J') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE", (VOTE=>$yes, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'N') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE", (VOTE=>$no, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'E') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE", (VOTE=>$abst, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'S') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$yes $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'H') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $yes", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'I') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'j') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE", (VOTE=>$yes, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'n') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE", (VOTE=>$no, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'e') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE", (VOTE=>$abst, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 's') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$yes $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'h') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $yes", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'i') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_IFCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    if ($text1) {
 | 
				
			||||||
 | 
					      if ($firstrun) {
 | 
				
			||||||
 | 
					        $text .= "    " . $text1 . "\n";
 | 
				
			||||||
 | 
					        $firstrun = 0;
 | 
				
			||||||
 | 
					      } else  {
 | 
				
			||||||
 | 
					        $text .= $fill . $text1 . "\n";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  @rule = split (//, $rules[$n-1]->{then_compl});
 | 
				
			||||||
 | 
					  $text .= "  ..." . UVmessage::get ("RULES_THEN") . "\n";
 | 
				
			||||||
 | 
					  $firstrun = 1;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  for (my $i=0; $i<@rule; $i++) {
 | 
				
			||||||
 | 
					    my $text1 = "";
 | 
				
			||||||
 | 
					    if ($rule[$i] eq 'J') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE", (VOTE=>$yes, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'N') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE", (VOTE=>$no, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'E') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE", (VOTE=>$abst, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'S') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$yes $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'H') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $yes", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'I') {
 | 
				
			||||||
 | 
					      $fill = "    $and ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'j') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE", (VOTE=>$yes, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'n') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE", (VOTE=>$no, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'e') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE", (VOTE=>$abst, GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 's') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$yes $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'h') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $yes", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    } elsif ($rule[$i] eq 'i') {
 | 
				
			||||||
 | 
					      $fill = "    $or ";
 | 
				
			||||||
 | 
					      $text1 = UVmessage::get ("RULES_THENCLAUSE",
 | 
				
			||||||
 | 
					                               (VOTE=>"$abst $or $no", GROUP=>$groups[$i]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    if ($text1) {
 | 
				
			||||||
 | 
					      if ($firstrun) {
 | 
				
			||||||
 | 
					        $text .= "    " . $text1 . "\n";
 | 
				
			||||||
 | 
					        $firstrun = 0;
 | 
				
			||||||
 | 
					      } else  {
 | 
				
			||||||
 | 
					        $text .= $fill . $text1 . "\n";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return $text . "\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
							
								
								
									
										336
									
								
								UVsendmail.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										336
									
								
								UVsendmail.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,336 @@
 | 
				
			||||||
 | 
					# UVsendmail: functions for sending mails
 | 
				
			||||||
 | 
					# Used by uvvote.pl, uvcfv.pl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package UVsendmail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVtemplate;
 | 
				
			||||||
 | 
					use MIME::Words;
 | 
				
			||||||
 | 
					use Text::Wrap qw(wrap $columns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set columns for Text::Wrap
 | 
				
			||||||
 | 
					$columns = $config{rightmargin};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use vars qw($VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Module version
 | 
				
			||||||
 | 
					$VERSION = "0.9";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $num = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# generation of acknowledge and error mails (don't sends them out yet)       #
 | 
				
			||||||
 | 
					# each mail is saved in a different file and a control file containing       #
 | 
				
			||||||
 | 
					# filename and envelope-to address is generated.                             #
 | 
				
			||||||
 | 
					# Parameters: mail address, fixed part of subject and body of mail (strings) #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					sub mail {
 | 
				
			||||||
 | 
					  my ($addr, $subject, $text, $reference, $replyto) = @_;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  # address set?
 | 
				
			||||||
 | 
					  if ($addr) {
 | 
				
			||||||
 | 
					    # generate mail to sender
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					    $template->setKey('from' => mimeencode($config{mailfrom}));
 | 
				
			||||||
 | 
					    $template->setKey('subject' => mimeencode("$config{votename} - $subject"));
 | 
				
			||||||
 | 
					    $template->setKey('address' => $addr);
 | 
				
			||||||
 | 
					    $template->setKey('reference' => $reference) if ($reference);
 | 
				
			||||||
 | 
					    $template->setKey('reply-to' => $replyto) if ($replyto);
 | 
				
			||||||
 | 
					    $template->setKey('usevote-version' => $usevote_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $message = $template->processTemplate($config{'tpl_mailheader'});
 | 
				
			||||||
 | 
					    $message .= "\n" . $text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # get envelope-to addresses
 | 
				
			||||||
 | 
					    my $envaddr = $addr;
 | 
				
			||||||
 | 
					    $envaddr .= " $config{mailcc}" if ($config{mailcc});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $mailfile = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # search for file names
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					      $num++;
 | 
				
			||||||
 | 
					      $mailfile = "$config{tmpdir}/ack.$num";
 | 
				
			||||||
 | 
					    } while (-e $mailfile);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # write mail in a file and append a line at the control file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    open (CONTROL, ">>$config{controlfile}") or print STDERR "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERROPENCONTROL", (FILE => $config{controlfile})), "\n"; 
 | 
				
			||||||
 | 
					    print CONTROL "$mailfile\t$envaddr\n";
 | 
				
			||||||
 | 
					    close (CONTROL) or print STDERR "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERRCLOSECONTROL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    open (MAIL, ">$mailfile") or print STDERR "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERROPENMAIL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					    print MAIL $message;
 | 
				
			||||||
 | 
					    close (MAIL) or print STDERR "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERRCLOSEMAIL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}                                                                                      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Send previously generated acknowledge or error mails.                      #
 | 
				
			||||||
 | 
					# Depending on configuration mails are piped to your MTA or send via SMTP.   #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub send {
 | 
				
			||||||
 | 
					  unless (-e $config{controlfile}) {
 | 
				
			||||||
 | 
					    print "\n", UVmessage::get("SENDMAIL_NOMAILS", (FILE => $config{controlfile})),
 | 
				
			||||||
 | 
					          "\n\n";
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  open (CONTROL, "<$config{controlfile}") or die "\n\n",
 | 
				
			||||||
 | 
					    UVmessage::get("SENDMAIL_ERROPENCONTROL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					  my @mailinfo = <CONTROL>;
 | 
				
			||||||
 | 
					  close (CONTROL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print UVmessage::get("SENDMAIL_SENDING"), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($config{smtp}) {
 | 
				
			||||||
 | 
					    # send mails via SMTP
 | 
				
			||||||
 | 
					    use Net::SMTP;
 | 
				
			||||||
 | 
					    my $smtp = Net::SMTP->new("$config{smtpserver}:$config{smtpport}",
 | 
				
			||||||
 | 
					                              Hello => $config{smtphelo});
 | 
				
			||||||
 | 
					    die UVmessage::get("SENDMAIL_SMTP_CONNREFUSED") . "\n\n" unless ($smtp);
 | 
				
			||||||
 | 
					    if ($config{smtpauth}) {
 | 
				
			||||||
 | 
					      $smtp->auth($config{smtpuser}, $config{smtppass})
 | 
				
			||||||
 | 
					        or die UVmessage::get("SENDMAIL_SMTP_CONNREFUSED") . "\n" .
 | 
				
			||||||
 | 
					               $smtp->code() . ' ' . $smtp->message() . "\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $errors = 0;
 | 
				
			||||||
 | 
					    my $missingfiles = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    open (CONTROL, ">$config{controlfile}") or die  "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERROPENCONTROL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach my $mail (@mailinfo) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      chomp ($mail);
 | 
				
			||||||
 | 
					      next unless $mail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my ($file, $envelope) = split(/\t/, $mail);
 | 
				
			||||||
 | 
					      my $notfound = 0;
 | 
				
			||||||
 | 
					      open (MAIL, "<$file") or $notfound = 1;
 | 
				
			||||||
 | 
					      if ($notfound) {
 | 
				
			||||||
 | 
					        print STDERR UVmessage::get("SENDMAIL_ERRNOTFOUND") . "\n";
 | 
				
			||||||
 | 
					        $missingfiles++;
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      my $message = join('', <MAIL>);
 | 
				
			||||||
 | 
					      close (MAIL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      next unless $message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $smtp->reset();
 | 
				
			||||||
 | 
					      $smtp->mail($config{envelopefrom});
 | 
				
			||||||
 | 
					      unless ($smtp->ok()) {
 | 
				
			||||||
 | 
					        print STDERR UVmessage::get("SENDMAIL_SMTP_INVRCPT", (RCPT => $envelope)),
 | 
				
			||||||
 | 
					                     "\n", $smtp->code(), ' ', $smtp->message(), "\n";
 | 
				
			||||||
 | 
					        $errors++;
 | 
				
			||||||
 | 
					        next;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					      my $onesent = 0;
 | 
				
			||||||
 | 
					      my $onefail = 0;
 | 
				
			||||||
 | 
					      foreach my $addr (split(/ +/, $envelope)) {
 | 
				
			||||||
 | 
					        $smtp->to($addr);
 | 
				
			||||||
 | 
					        if ($smtp->ok()) {
 | 
				
			||||||
 | 
					          $onesent = 1;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          print CONTROL ($onefail ? " " : "$file\t");
 | 
				
			||||||
 | 
					          print CONTROL $addr;
 | 
				
			||||||
 | 
					          print STDERR UVmessage::get("SENDMAIL_SMTP_INVRCPT", (RCPT => $envelope)),
 | 
				
			||||||
 | 
					                       "\n", $smtp->code(), ' ', $smtp->message(), "\n";
 | 
				
			||||||
 | 
					          $errors++;
 | 
				
			||||||
 | 
					          $onefail = 1;
 | 
				
			||||||
 | 
					          next;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print CONTROL "\n" if ($onefail);
 | 
				
			||||||
 | 
					      next unless $onesent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $smtp->data();
 | 
				
			||||||
 | 
					      if ($smtp->ok()) {
 | 
				
			||||||
 | 
					        $smtp->datasend($message);
 | 
				
			||||||
 | 
					        $smtp->dataend();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      unless ($smtp->ok()) {
 | 
				
			||||||
 | 
					        print STDERR UVmessage::get("SENDMAIL_SMTP_INVRCPT", (RCPT => $envelope)),
 | 
				
			||||||
 | 
					                     "\n", $smtp->code(), ' ', $smtp->message(), "\n";
 | 
				
			||||||
 | 
					        $errors++;
 | 
				
			||||||
 | 
					        next; 
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      unlink ($file) unless ($onefail);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $smtp->quit();
 | 
				
			||||||
 | 
					    close (CONTROL) or die "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERRCLOSECONTROL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($errors) {
 | 
				
			||||||
 | 
					      print STDERR "\n".wrap('', '', "$errors ".UVmessage::get("SENDMAIL_ERROCCURED"))."\n\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($missingfiles) {
 | 
				
			||||||
 | 
					      print STDERR wrap('', '', "$missingfiles " .
 | 
				
			||||||
 | 
					                   UVmessage::get("SENDMAIL_MISSINGFILES")), "\n\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach my $mail (@mailinfo) {
 | 
				
			||||||
 | 
					      next unless $mail;
 | 
				
			||||||
 | 
					      chomp($mail);
 | 
				
			||||||
 | 
					      my ($file, @rcpt) = split(/\s+/, $mail);
 | 
				
			||||||
 | 
					      open (DOMAIL, ">>$config{domailfile}");
 | 
				
			||||||
 | 
					      print DOMAIL "$config{mailcmd} ";
 | 
				
			||||||
 | 
					      foreach my $rcpt (@rcpt) {
 | 
				
			||||||
 | 
					        print DOMAIL "'$rcpt' ";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      print DOMAIL "<$file && rm $file ; $config{sleepcmd}\n";
 | 
				
			||||||
 | 
					      close (DOMAIL)
 | 
				
			||||||
 | 
					        or print STDERR "\n\n", UVmessage::get("SENDMAIL_ERRCLOSEDOMAIL"), "\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    chmod(0700, $config{domailfile});
 | 
				
			||||||
 | 
					    system($config{domailfile});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  opendir (DIR, $config{tmpdir});
 | 
				
			||||||
 | 
					  my @files = grep (/^ack\.\d+/, readdir (DIR));
 | 
				
			||||||
 | 
					  closedir (DIR);
 | 
				
			||||||
 | 
					  return 0 if (@files);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unlink $config{controlfile} or print STDERR "\n\n",
 | 
				
			||||||
 | 
					    UVmessage::get("SENDMAIL_ERRDELCONTROL", (FILE => $config{controlfile})), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unless ($config{smtp}) {
 | 
				
			||||||
 | 
					    unlink $config{domailfile} or print STDERR "\n\n",
 | 
				
			||||||
 | 
					      UVmessage::get("SENDMAIL_ERRDELCONTROL", (FILE => $config{domailfile})), "\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Encodes a string for use in mail headers                                   #
 | 
				
			||||||
 | 
					#                                                                            #
 | 
				
			||||||
 | 
					# Parameters: $text = string to encode.                                      #
 | 
				
			||||||
 | 
					# Returns:  $newtext = encoded string.                                       #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					sub mimeencode {
 | 
				
			||||||
 | 
					  my ($text) = @_;
 | 
				
			||||||
 | 
					  my @words = split(/ /, $text);
 | 
				
			||||||
 | 
					  my $line = '';
 | 
				
			||||||
 | 
					  my @lines;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  foreach my $word (@words) {
 | 
				
			||||||
 | 
					    my $sameword = 0;
 | 
				
			||||||
 | 
					    $word =~ s/\n//g;
 | 
				
			||||||
 | 
					    my $encword;
 | 
				
			||||||
 | 
					    if ($word =~ /[\x7F-\xFF]/) {
 | 
				
			||||||
 | 
					      $encword = MIME::Words::encode_mimeword($word, 'Q', 'ISO-8859-1');
 | 
				
			||||||
 | 
					    } elsif (length($word) > 75) {
 | 
				
			||||||
 | 
					      $encword = MIME::Words::encode_mimeword($word, 'Q', 'us-ascii');
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $encword = $word;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    # no more than 75 chars per line allowed
 | 
				
			||||||
 | 
					    if (length($encword) > 75) {
 | 
				
			||||||
 | 
					      while ($encword) {
 | 
				
			||||||
 | 
					        if ($encword =~ /(^=\?[-\w]+\?\w\?)(.{55}.*?)((=.{2}|[^=]{3}).*\?=)$/) {
 | 
				
			||||||
 | 
					          addword($1 . $2 . '?=', \$line, \@lines, $sameword);
 | 
				
			||||||
 | 
					          $encword = $1 . $3;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          addword($encword, \$line, \@lines, $sameword);
 | 
				
			||||||
 | 
					          $encword = '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $sameword = 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      addword($encword, \$line, \@lines, $sameword);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  my $delim = (@lines) ? ' ' : '';
 | 
				
			||||||
 | 
					  push(@lines, $delim . $line) if ($line);
 | 
				
			||||||
 | 
					  return join('', @lines);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Adds a word to a MIME encoded string, inserts linefeed if necessary        #
 | 
				
			||||||
 | 
					#                                                                            #
 | 
				
			||||||
 | 
					# Parameters:                                                                #
 | 
				
			||||||
 | 
					#   $word = word to add                                                      #
 | 
				
			||||||
 | 
					#   $line = current line                                                     #
 | 
				
			||||||
 | 
					#   $lines = complete text (without current line)                            #
 | 
				
			||||||
 | 
					#   $sameword = boolean switch, indicates that this is another part of       #
 | 
				
			||||||
 | 
					#               the last word (for encoded words > 75 chars)                 #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					sub addword {
 | 
				
			||||||
 | 
					  my ($word, $line, $lines, $sameword) = @_;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  # If the passed fragment is a new word (and not another part of the
 | 
				
			||||||
 | 
					  # previous): Check if it is MIME encoded
 | 
				
			||||||
 | 
					  if (!$sameword && $word =~ /^(=\?[^\?]+?\?[QqBb]\?)(.+\?=[^\?]*)$/) {
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    # Word is encoded, save without the MIME header
 | 
				
			||||||
 | 
					    # (e.g. "t=E4st?=" instead of "?iso-8859-1?q?t=E4st?=")
 | 
				
			||||||
 | 
					    my $charset = $1;
 | 
				
			||||||
 | 
					    my $newword = $2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($$line =~ /^(=\?[^\?]+\?[QqBb]\?)(.+)\?=$/) {
 | 
				
			||||||
 | 
					      # Previous word was encoded, too:
 | 
				
			||||||
 | 
					      # Delete the trailing "?=" and insert an underline character (=space)
 | 
				
			||||||
 | 
					      # (space between to encoded words is ignored)
 | 
				
			||||||
 | 
					      if ($1 eq $charset) {
 | 
				
			||||||
 | 
					        if (length($1.$2)+length($newword)>75) {
 | 
				
			||||||
 | 
					          my $delim = (@$lines) ? ' ' : '';
 | 
				
			||||||
 | 
					          push(@$lines, "$delim$1$2_?=\n");
 | 
				
			||||||
 | 
					          $$line = $word;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          $$line = $1 . $2 . '_' . $newword;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        if (length("$$line $word")>75) {
 | 
				
			||||||
 | 
					          my $delim = (@$lines) ? ' ' : '';
 | 
				
			||||||
 | 
						  push(@$lines, "$delim$1$2_?=\n");
 | 
				
			||||||
 | 
					          $$line = $word;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
					          $$line = "$1$2_?= $word";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # New word is not encoded: simply append it, but check for line length
 | 
				
			||||||
 | 
					  # and add a newline if necessary
 | 
				
			||||||
 | 
					  if (length($$line) > 0) {
 | 
				
			||||||
 | 
					    if (length($$line) + length($word) >= 75) {
 | 
				
			||||||
 | 
					      my $delim = (@$lines) ? ' ' : '';
 | 
				
			||||||
 | 
					      push(@$lines, "$delim$$line\n");
 | 
				
			||||||
 | 
					      $$line = $word;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $$line .= " $word";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # line is empty
 | 
				
			||||||
 | 
					    $$line = $word;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
							
								
								
									
										810
									
								
								UVtemplate.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										810
									
								
								UVtemplate.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,810 @@
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					package UVtemplate;
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 NAME
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UVtemplate - Templateverarbeitung und String-Formatierungen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 SYNOPSIS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  use UVtemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $plate  = UVtemplate->new([%keys]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $plate->setKey(%keys);
 | 
				
			||||||
 | 
					  $item   = $plate->addListItem($name, %keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $string = $plate->processTemplate($file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 DESCRIPTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mit Hilfe von UVtemplate, wird die komplette Aufbereitung und 
 | 
				
			||||||
 | 
					Formatierung der Programmausgaben nicht nur ausgelagert sondern
 | 
				
			||||||
 | 
					auch so flexibiliert, dass sie jederzeit angepasst werden kann,
 | 
				
			||||||
 | 
					ohne das im eigentlichen Programmcode veraendert werden muss.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Auf Programmseite wird eine Datenstruktur mit Schluessel-Wert
 | 
				
			||||||
 | 
					Paaren erzeugt. In den Template-Dateien werden dann spaeter die
 | 
				
			||||||
 | 
					jeweiligen Schluessel, durch ihre im Programm festgelegten 
 | 
				
			||||||
 | 
					Werte ersetzt. Zusaetzlich ist es moeglich Schluessel zu Listen
 | 
				
			||||||
 | 
					zusammenzufassen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Da es sich bei den Templates um Ascii-Texte handelt, gibt es 
 | 
				
			||||||
 | 
					zusaetzlich die Moeglichkeit die Werte der Schluessel zuformatieren
 | 
				
			||||||
 | 
					um eine einheitliche Ausgabe zu ermoeglichen. D.h. es kann z.B. durch 
 | 
				
			||||||
 | 
					das Anhaengen von Leerzeichen dafuer gesorgt werden, das ein Schluessel
 | 
				
			||||||
 | 
					einer Liste immer 60 Zeichen lang ist um ansehnliche Tabellen auszugeben.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=over 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use vars qw( $VERSION $functions @dirs);
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$VERSION = 0.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Eine neues Objekt vom Typ UVtemplate anlegen. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $plate = UVtemplate->new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Als Parameter koennen gleich beliebig viele Schluessel-Wert-Paare
 | 
				
			||||||
 | 
					uebergeben werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub new{
 | 
				
			||||||
 | 
					  my $class = shift;
 | 
				
			||||||
 | 
					  my $self  = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ref($class)){
 | 
				
			||||||
 | 
					    $self->{FATHER} = $class;
 | 
				
			||||||
 | 
					    bless($self, ref($class));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }else{
 | 
				
			||||||
 | 
					    bless($self, $class);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $self->setKey(@_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item setKey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Schluessel und zugehoerige Werte im Objekt speichern.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $plate->setKey( vote-addr => 'to-vote@dom.ain' );
 | 
				
			||||||
 | 
					  $plate->setKey( datenschutz => 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ist der zu speichernde Schluessel bereits vorhanden, wird er
 | 
				
			||||||
 | 
					durch den neuen Wert ueberschrieben.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub setKey{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my %param = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $key (keys(%param)){
 | 
				
			||||||
 | 
					    $self->{KEYS}->{$key} = $param{$key};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item addListItem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Erzeugt ein neues Objekt vom Typ UVtemplate und fuegt es der 
 | 
				
			||||||
 | 
					angebenen Liste hinzu.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $plate->addListItem(name => 'Musterman', email => 'em@il');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Da sich Listen wie normale Schluessel-Wert Paare verhalten, 
 | 
				
			||||||
 | 
					wird die Liste als Array ueber UVtemplate-Objekte unter dem
 | 
				
			||||||
 | 
					definiertem Schluessel abgelegt. Ist dieser Schluessel bereits
 | 
				
			||||||
 | 
					gesetzt und enthaehlt keinen Array, so bricht die Funktion ab.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub addListItem{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my $list = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # pruefen ob key angegeben ist und falls key vorhanden
 | 
				
			||||||
 | 
					  # eine liste vorliegt
 | 
				
			||||||
 | 
					  return unless ($list && (not($self->{KEYS}->{$list}) ||
 | 
				
			||||||
 | 
					    UNIVERSAL::isa($self->{KEYS}->{$list}, 'ARRAY')));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # neues Element erzeugen
 | 
				
			||||||
 | 
					  my $new = $self->new( @_ );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # an listen anhaengen
 | 
				
			||||||
 | 
					  push(@{$self->{KEYS}->{$list}}, $new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # referenz zurueckgeben
 | 
				
			||||||
 | 
					  return $new;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item getKey($key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Den Wert eines Schluessel ermitteln.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $value = $plate->getKey('email');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ist der Wert im Objekt nicht gesetzt, wird - falls es sich um ein
 | 
				
			||||||
 | 
					Element einer Liste handelt - rekursiv beim Vater weiter gesucht.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					So stehen allen Kindern auch die Schluessel-Wert Paare ihrer Eltern
 | 
				
			||||||
 | 
					zur Verfuegung.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zum Schluss wird noch geprueft, ob der Schluessel in usevote.cfg
 | 
				
			||||||
 | 
					gesetzt wurde. Dadurch sind alle Konfigurationsoptionen direkt
 | 
				
			||||||
 | 
					in Templates nutzbar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub getKey{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my $key  = $_[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  do{
 | 
				
			||||||
 | 
					    $value = $self->{KEYS}->{$key};
 | 
				
			||||||
 | 
					    $self  = $self->{FATHER};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }while(!defined($value) && $self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!defined($value) && defined($config{$key})) {
 | 
				
			||||||
 | 
					    $value = $config{$key};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub getRules{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  do{
 | 
				
			||||||
 | 
					    return $self->{RULES} if ($self->{RULES});
 | 
				
			||||||
 | 
					    $self = $self->{FATHER};
 | 
				
			||||||
 | 
					  }while($self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item getConvKey{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Einen Format ermitteln.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $value = $plate->getConvKey('email-adresse');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Diese Funktion ueberprueft ob eine Formatierung mit den entsprechenden
 | 
				
			||||||
 | 
					Schluessel definiert ist und ruft dementsprechend die dort definierten
 | 
				
			||||||
 | 
					Funktionen ueber der Datenstruktur auf.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ist kein solches Format definiert, wird der Wert des Schluessel mit
 | 
				
			||||||
 | 
					einem solchen Namen zurueckgegeben. (Es wird intern getKey aufgerufen).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub getConvKey{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my $key  = $_[0] || return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $rules = $self->getRules();
 | 
				
			||||||
 | 
					  my $value = $self->getKey($key);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  $value = '' unless (defined($value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($rules && ($rules->{$key})){
 | 
				
			||||||
 | 
					    my @funcs = @{$rules->{$key}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach my $func (@funcs){
 | 
				
			||||||
 | 
					      my ($name, @params) = @$func;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      if ($functions->{$name}){
 | 
				
			||||||
 | 
					        $value = $functions->{$name}->($self, $value, @params);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					      }else{
 | 
				
			||||||
 | 
					        print STDERR "format function '$name' not found!\n";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item processTemplate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Daten des Objekts in ein Template einfuegen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $string = $plate->processTemplate('template/info.txt');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die angebene Datei wird eingelesen, zerlegt und danach
 | 
				
			||||||
 | 
					die enstprechenden Platzhalter durch die (formatierten) 
 | 
				
			||||||
 | 
					Werte aus der Datenstruktur ersetzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=cut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub processTemplate{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my $file = $_[0] || return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my ($rules, $body) = _split_file($file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # konvertierungsregeln parsen
 | 
				
			||||||
 | 
					  $self->{RULES} = _parse_rules($rules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # template zerlegen (zuerst fuehrende leerzeilen entfernen!)
 | 
				
			||||||
 | 
					  $body =~ s/^\n+//s;	
 | 
				
			||||||
 | 
					  my $token = UVtemplate::scan->new(string => $body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # daten einsetzen
 | 
				
			||||||
 | 
					  return $token->processData($self);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _split_file{
 | 
				
			||||||
 | 
					  my $file = $_[0] || return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $fname = _complete_filename($file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unless ($fname){
 | 
				
			||||||
 | 
					    print STDERR "couldnt find '$file'\n";
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my (@rules, @body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  open(PLATE, $fname);
 | 
				
			||||||
 | 
					  my @lines = <PLATE>;
 | 
				
			||||||
 | 
					  close(PLATE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $body = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $line (@lines){
 | 
				
			||||||
 | 
					    if ($line =~ m/^== TEMPLATE/){
 | 
				
			||||||
 | 
					      $body = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      if ($body){
 | 
				
			||||||
 | 
					        push(@body, $line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      }else{
 | 
				
			||||||
 | 
					        push(@rules, $line);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # falls kein Separator definiert war, wird der komplette Text
 | 
				
			||||||
 | 
					  # als Body interpretiert. Es gibt keine Regeln!
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  unless ($body){
 | 
				
			||||||
 | 
					    @body  = @rules;
 | 
				
			||||||
 | 
					    @rules = ();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # und nun wieder zu Strings zusammenpappen
 | 
				
			||||||
 | 
					  return (join('', @rules), join('', @body));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _complete_filename{
 | 
				
			||||||
 | 
					  my $file = $_[0] || return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $dirs = $UVconfig::config{templatedir};
 | 
				
			||||||
 | 
					     @dirs = split(/\s*,\s*/, $dirs) if $dirs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $fname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $dir (@dirs, '.'){
 | 
				
			||||||
 | 
					    $fname = "$dir/$file";
 | 
				
			||||||
 | 
					    return $fname if (-r $fname);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Konvertierungs-Regeln
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_rules{
 | 
				
			||||||
 | 
					  my $string = $_[0] || return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @stack;
 | 
				
			||||||
 | 
					  my $rules = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $this = [];
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  while (length($string) > 0){
 | 
				
			||||||
 | 
					    _strip_chars(\$string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $token = _parse_token(\$string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($token){
 | 
				
			||||||
 | 
					      push(@stack, $token);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      _strip_chars(\$string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ($string =~ s/^:=//){
 | 
				
			||||||
 | 
					        # neuen Schluessel vom Stack holen
 | 
				
			||||||
 | 
					        my $key = pop(@stack);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						# restlichen Stack auf alten Schluessel packen
 | 
				
			||||||
 | 
						push(@$this, [ @stack ]);
 | 
				
			||||||
 | 
						@stack = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# neuen Schluessel anlegen
 | 
				
			||||||
 | 
						$rules->{$key} = $this = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      }elsif($string =~ s/^\|//){
 | 
				
			||||||
 | 
					        # stack auf schluessel packen
 | 
				
			||||||
 | 
						push(@$this, [ @stack ]);
 | 
				
			||||||
 | 
						@stack = ();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      # fehlermeldung ausgeben (nacharbeiten!)
 | 
				
			||||||
 | 
					      print STDERR "Syntaxerror in Definition\n";
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # den Rest vom Stack abarbeiten
 | 
				
			||||||
 | 
					  push(@$this, [ @stack ]) if @stack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $rules;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _strip_chars{
 | 
				
			||||||
 | 
					  my $line = $_[0] || return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # führenden whitespace entfernen
 | 
				
			||||||
 | 
					  $$line =~ s/^\s+//;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # kommentare bis zum nächsten Zeilenumbruch entfernen
 | 
				
			||||||
 | 
					  $$line =~ s/^#.*$//m;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_token{
 | 
				
			||||||
 | 
					  my $string = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($$string =~ s/^(["'])//){
 | 
				
			||||||
 | 
					    return _parse_string($string, $1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }else{
 | 
				
			||||||
 | 
					    return _parse_ident($string);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_string{
 | 
				
			||||||
 | 
					  my ($string, $limit) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while ($$string){
 | 
				
			||||||
 | 
					    if ($$string =~ s/^$limit//){
 | 
				
			||||||
 | 
					      $$string =~ s/^\s*//;
 | 
				
			||||||
 | 
					      return $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }elsif($$string =~ s/^\\(.)//){
 | 
				
			||||||
 | 
					      $value .= $1;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      $$string =~ s/^[^$limit\\]*//;
 | 
				
			||||||
 | 
					      $value .= $&;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # end of line 
 | 
				
			||||||
 | 
					  return $value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_ident{
 | 
				
			||||||
 | 
					  my $string = shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($$string =~ s/^([A-Za-z0-9-]+)\s*//){
 | 
				
			||||||
 | 
					    return $1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BEGIN{
 | 
				
			||||||
 | 
					  $functions = \%UVconfig::functions;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					package UVtemplate::scan;
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub new{
 | 
				
			||||||
 | 
					  my $class = shift;
 | 
				
			||||||
 | 
					  my %param = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $self  = {};
 | 
				
			||||||
 | 
					  bless($self, $class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $self->parseFile($param{file})     if defined($param{file});
 | 
				
			||||||
 | 
					  $self->parseString($param{string}) if defined($param{string});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub processData{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my $data = $_[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return _process_data($self->{toks}, $data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _process_data{
 | 
				
			||||||
 | 
					  my ($toref, $data) = @_;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  my $string = '';
 | 
				
			||||||
 | 
					  my $length = 0;
 | 
				
			||||||
 | 
					  my $empty  = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $token (@$toref){
 | 
				
			||||||
 | 
					    if (ref($token)){
 | 
				
			||||||
 | 
					      my $before = length($string);
 | 
				
			||||||
 | 
					         $empty  = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					      if ($token->[0] eq 'VAR'){
 | 
				
			||||||
 | 
					        my $value = $data->getConvKey(_process_data($token->[1], $data));
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					        if (defined($value) && length($value)){
 | 
				
			||||||
 | 
					          $string .= $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}else{
 | 
				
			||||||
 | 
						  $string .= _process_data($token->[2], $data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      }elsif($token->[0] eq 'IF'){
 | 
				
			||||||
 | 
					        if ($data->getConvKey(_process_data($token->[1], $data))){
 | 
				
			||||||
 | 
					          $string .= _process_data($token->[2], $data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}else{
 | 
				
			||||||
 | 
					          $string .= _process_data($token->[3], $data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					     
 | 
				
			||||||
 | 
					      }elsif($token->[0] eq 'LOOP'){
 | 
				
			||||||
 | 
					        my $nodes = $data->getConvKey(_process_data($token->[1], $data));
 | 
				
			||||||
 | 
						my @block;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($nodes && (UNIVERSAL::isa($nodes, 'ARRAY'))){
 | 
				
			||||||
 | 
						  foreach my $node (@$nodes){
 | 
				
			||||||
 | 
					            push(@block, _process_data($token->[2], $node));
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  $string .= join(_process_data($token->[3], $data), @block);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $length = length($string);
 | 
				
			||||||
 | 
					      $empty  = 1 if ($before == $length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      if ($empty && ($string =~ m/(\n|^)$/s)){
 | 
				
			||||||
 | 
					        $empty = 0;		# Falls die letzte Zeile nur aus einem Token
 | 
				
			||||||
 | 
					        $token =~ s/^\n//s;	# ohne Inhalt bestand, wird die Zeile entfernt
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					      $string .= $token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Den String in einen Syntaxbaum abbilden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_token_string{
 | 
				
			||||||
 | 
					  my $self   = shift;
 | 
				
			||||||
 | 
					  my ($string, $intern) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my (@token, $toref); 
 | 
				
			||||||
 | 
					  my $data = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while ($string){
 | 
				
			||||||
 | 
					    if ($intern && $string =~ m/^(\]|\|)/){
 | 
				
			||||||
 | 
					      last;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    }elsif ($string =~ s/^\[//){
 | 
				
			||||||
 | 
					      my $orig = $string;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					      ($toref, $string) = $self->_parse_token($string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (@$toref){
 | 
				
			||||||
 | 
					        push (@token, $data) if $data;
 | 
				
			||||||
 | 
						$data = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        push(@token, $toref) 
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ($string !~ s/^\]//){
 | 
				
			||||||
 | 
					        my $pos = $self->{lines} - _count_lines($orig) + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print STDERR "Scanner: [$pos] missing right bracket\n";
 | 
				
			||||||
 | 
						return (\@token, $string);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    }elsif($string =~ s/^\\n//s){
 | 
				
			||||||
 | 
					      $data .= "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }elsif($string =~ s/^\\(.)//s){
 | 
				
			||||||
 | 
					      $data .= $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }elsif($intern){
 | 
				
			||||||
 | 
					      $string =~ s/^([^\]\[\|\\]+)//s;
 | 
				
			||||||
 | 
					      $data  .= $1;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      $string =~ s/^([^\[\\]+)//s;
 | 
				
			||||||
 | 
					      $data  .= $1;
 | 
				
			||||||
 | 
					    } 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  push (@token, $data) if length($data);
 | 
				
			||||||
 | 
					  return (\@token, $string)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_token{
 | 
				
			||||||
 | 
					  my $self   = shift; 
 | 
				
			||||||
 | 
					  my $string = $_[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @token = ();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if ($string =~ s/^\$//s){ 
 | 
				
			||||||
 | 
					    # Variablen - Syntax: [$key[|<else>]] 
 | 
				
			||||||
 | 
					    push (@token, 'VAR');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }elsif ($string =~ s/^\?//s){
 | 
				
			||||||
 | 
					    # Bedingung - Syntax: [?if|<then>[|<else>]]
 | 
				
			||||||
 | 
					    push (@token, 'IF');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }elsif ($string =~ s/^\@//s){
 | 
				
			||||||
 | 
					    # Schleifen - Syntax: [@key|<block>[|<sep>]]
 | 
				
			||||||
 | 
					    push (@token, 'LOOP');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }elsif ($string =~ s/^#//s){
 | 
				
			||||||
 | 
					    # Kommentare - Syntax: [# ... ]
 | 
				
			||||||
 | 
					    $string = _parse_comment($string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (\@token, $string);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  }else{
 | 
				
			||||||
 | 
					    print STDERR "unknown token in template\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $toref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ($toref, $string) = $self->_parse_token_string($string, 1);
 | 
				
			||||||
 | 
					  push(@token, $toref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while ($string =~ s/^\|//){
 | 
				
			||||||
 | 
					    ($toref, $string) = $self->_parse_token_string($string, 1);
 | 
				
			||||||
 | 
					    push(@token, $toref);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (\@token, $string);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _parse_comment{
 | 
				
			||||||
 | 
					  my $string = $_[0];
 | 
				
			||||||
 | 
					  my $count  = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while($string && $count) {
 | 
				
			||||||
 | 
					    $string =~ s/^[^\[\]\\]+//s; # alles außer Klammern und Backslash wegwerfen
 | 
				
			||||||
 | 
					    $string =~ s/^\\.//;	# alles gesperrte löschen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $count++ if $string =~ s/^\[//;
 | 
				
			||||||
 | 
					    $count-- if $string =~ s/^\]//;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $string = ']'.$string if !$count;
 | 
				
			||||||
 | 
					  return $string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub parseString{
 | 
				
			||||||
 | 
					  my $self = shift;
 | 
				
			||||||
 | 
					  my $text = $_[0];  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $self->{lines} = _count_lines($text);
 | 
				
			||||||
 | 
					  my ($toref, $rest) = $self->_parse_token_string($text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $self->{toks} = $toref;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub _count_lines{
 | 
				
			||||||
 | 
					  return 0 unless defined($_[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my ($string, $count) = ($_[0], 1);
 | 
				
			||||||
 | 
					  $count++ while($string =~ m/\n/sg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					#----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=back
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 SYNTAX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Eine Templatedatei besteht aus zwei Teilen. Am Anfang werden die 
 | 
				
			||||||
 | 
					Formatierungen bestimmter Schluessel definiert und nach einem
 | 
				
			||||||
 | 
					Trenner folgt der eigentlich Template-Koerper, der dann von Programm
 | 
				
			||||||
 | 
					bearbeitet und ausgegeben wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  format-key := function1 param | function2 param
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  == TEMPLATE ====================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Ich bin nun das eigentliche Template:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  format-key: [$format-key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Der Trenner beginnt mit den Zeichen '== TEMPLATE' danach koennen
 | 
				
			||||||
 | 
					beliebige Zeichen folgen um die beiden Sektionen optisch voneinander 
 | 
				
			||||||
 | 
					abzugrenzen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wenn es keine Formatierungsanweisungen gibt, kann der Trenner auch
 | 
				
			||||||
 | 
					weggelassen werden. D.h. wenn kein Trenner gefunden wird, wird der
 | 
				
			||||||
 | 
					komplette Text als Template-Koerper betrachtet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head2 Template-Koerper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Im Template-Koerper werden die zu ersetzenden Token durch eckige
 | 
				
			||||||
 | 
					Klammern abgegrenzt. Sollen eckige Klammern im Text ausgegeben werden
 | 
				
			||||||
 | 
					muessen diese durch einen Backslash freigestellt werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [$termersetzung] [@schleife] nur eine \[ Klammer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=over 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item $ - Termersetzung 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ersetzt den Token durch den Wert des angegeben Schluessels.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [$formatierung] [$schluessel]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Es wird zuerst nach einer Formatierung mit den entsprechenden
 | 
				
			||||||
 | 
					Bezeichner gesucht. Ist dies der Fall werden die entsprechenden
 | 
				
			||||||
 | 
					Funktionen ausgefuehrt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Kann kein Format gefunden, wird direkt in der Datenstruktur
 | 
				
			||||||
 | 
					nach einem Schhluessel mit dem angegeben Bezeichner gesucht
 | 
				
			||||||
 | 
					und sein Wert eingesetzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Schlussendlich ist es noch moeglich einen default-Wert zu
 | 
				
			||||||
 | 
					definieren, der eingesetzt wird, wenn keiner der obigen Wege
 | 
				
			||||||
 | 
					erfolgreich war.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Hallo [$name|Unbekannter]!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item ? - bedingte Verzeigung
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ueberprueft ob der Wert des angegebenen Formats/Schluessel
 | 
				
			||||||
 | 
					boolsch WAHR ist. Dementsprechend wird der then oder else
 | 
				
			||||||
 | 
					Block eingefuegt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [?if|then|else] oder auch nur [?if|then]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die then/else Bloecke werden natuerlich auch auf Tokens
 | 
				
			||||||
 | 
					geparst und diese dementsprechend ersetzt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item @ - Schleifen/Listen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Der nachfolgende Textblock wird fuer alle Elemente des durch
 | 
				
			||||||
 | 
					den Schluessel bezeichneten Arrays ausgefuehrt und eingefuegt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [@schluessel|block] oder [@schluessel|block|sep]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Als zweiter Parameter kann ein Separtor definiert werden, mit
 | 
				
			||||||
 | 
					dem sich z.B. kommaseparierte Listen erzeugen lassen, da der
 | 
				
			||||||
 | 
					Separator eben nur zwischen den Element eingefuegt wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Auch fuer Schleifen koennen Formatierungen genutzt werden.
 | 
				
			||||||
 | 
					Allerdings darf kein String zurueckgegeben werden, sondern
 | 
				
			||||||
 | 
					ein Array mit einer Menge von UVtemplate-Objekten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item # - Kommentare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Token die nach der Bearbeitungen entfernt werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [# mich sieht man nicht]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=item Sonstiges
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Um in Listen einen Zeilenumbruch zu erzwingen, muss 
 | 
				
			||||||
 | 
					lediglich ein '\n' eingefuegt werden, falls eine kompakte
 | 
				
			||||||
 | 
					Definition der Liste erfolgen soll.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [@names|[name] [email]\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=back
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head2 Formatierungen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Eine Formatierung besteht eigentlich nur aus dem entsprechenden
 | 
				
			||||||
 | 
					Namen und einer beliebigen Anzahl von Funktionsaufrufen:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  format := funktion param1 "param 2" | funktion param
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Aehnlich der Unix-Shell-Funktionalitaet, wird dabei die Ausgabe
 | 
				
			||||||
 | 
					einer Funktion an die folgende weitergeleitet. So ist es moeglich
 | 
				
			||||||
 | 
					verschiedenste simple Formatierungen zu kombinieren um nicht fuer
 | 
				
			||||||
 | 
					jeden Spezialfall eine neue Funktion schreiben zu muessen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die jeweilige Formatierungsfunktion erhaelt als Input die Datenstruktur,
 | 
				
			||||||
 | 
					den Output der vorherigen Funktion und die definierten Parameter in der
 | 
				
			||||||
 | 
					entsprechenden Reihenfolge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zahlen und einfache Bezeichner koennen direkt definiert werden. Sollen
 | 
				
			||||||
 | 
					Sonderzeichen oder Leerzeichen uebergeben werden muessen diese gequotet
 | 
				
			||||||
 | 
					werden. Dazu kann ' also auch " verwendet werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die Funktionen geben im Allgemeinen einen String zurueck. Im Rahmen
 | 
				
			||||||
 | 
					von Listen können auch Arrays uebergeben werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die erste Funktion duerfte ueblicherweise 'value' sein. Sie gibt den
 | 
				
			||||||
 | 
					des angegeben Schluessel zurueck, der dann von den folgenden Funktionen
 | 
				
			||||||
 | 
					definiert wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  name-60 := value name | fill-right 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Das Format "name-60" definiert also den Wert des Schluessel "name" der
 | 
				
			||||||
 | 
					um Leerzeichen aufgefuellt wird, bis eine Laenge von 60 Zeichen 
 | 
				
			||||||
 | 
					erreicht wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  name-email := value name | justify-behind mail 72
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"name-email" resultiert in einem String, der zwischen den Werten
 | 
				
			||||||
 | 
					von "name" und "email" genau so viele Leerzeichen enthaelt, damit
 | 
				
			||||||
 | 
					der gesamte String 72 Zeichen lang ist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wird dieses Format in einer Liste angewandt, erhaelt man eine Tabelle
 | 
				
			||||||
 | 
					in der die linke Spalte linksbuendig und die rechte Spalte entsprechend
 | 
				
			||||||
 | 
					rechtsbuendig ist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Soweit ein kleiner Ueberblick ueber die Formatierungen. 
 | 
				
			||||||
 | 
					Ausfuehrliche Funktionsbeschreibungen und weitere Beispiele finden
 | 
				
			||||||
 | 
					sich in der Dokumentation des Moduls UVformat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 SEE ALSO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					L<UVformats>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=head1 AUTHOR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cornell Binder <cobi@dex.de>
 | 
				
			||||||
							
								
								
									
										13
									
								
								bdsgtext.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								bdsgtext.cfg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					# Diese Datei enthaelt den Hinweistext auf die Datenschutzklausel,
 | 
				
			||||||
 | 
					# der im Wahlschein erscheint und auch bei eingegangenen Wahlscheinen
 | 
				
			||||||
 | 
					# wieder abgeprueft wird. Alle Zeilen, die mit dem Kommentarzeichen #
 | 
				
			||||||
 | 
					# anfangen, werden ignoriert.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					Zur Verarbeitung des Wahlscheines und inbesondere der Veroeffentlichung
 | 
				
			||||||
 | 
					des Ergebnisses ist deine Zustimmung zur Speicherung, Auswertung und
 | 
				
			||||||
 | 
					Veroeffentlichung deiner Stimmdaten (Name und E-Mail-Adresse in
 | 
				
			||||||
 | 
					Verbindung mit dem Stimmverhalten) im Rahmen dieses Verfahrens
 | 
				
			||||||
 | 
					erforderlich. Wenn du im Feld unterhalb dieses Absatzes "JA"
 | 
				
			||||||
 | 
					eintraegst, erklaerst du dich damit einverstanden. In allen anderen
 | 
				
			||||||
 | 
					Faellen wird der Wahlschein mit Ruecksicht auf das deutsche
 | 
				
			||||||
 | 
					Bundesdatenschutzgesetz verworfen und nicht gewertet.
 | 
				
			||||||
							
								
								
									
										42
									
								
								mailpatterns.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								mailpatterns.cfg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					# Mailadressen, die auf diese Kriterien zutreffen, werden als verdaechtig
 | 
				
			||||||
 | 
					# angesehen und zurueckgewiesen. Im interaktiven Modus kann der Wahlleiter 
 | 
				
			||||||
 | 
					# im Einzelfall entscheiden.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Bitte ein Pattern (Regular Expression) pro Zeile eingeben.
 | 
				
			||||||
 | 
					# Achtung, es wird so benutzt, wie es hier steht, also auf fuehrende oder
 | 
				
			||||||
 | 
					# abschliessende Leerzeichen aufpassen!
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Alle Zeilen, die mit dem Kommentarzeichen # anfangen, werden ignoriert.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@anon\.penet\.fi
 | 
				
			||||||
 | 
					@anon\.sub\.net
 | 
				
			||||||
 | 
					anonymous@mixmaster\.nullify\.org
 | 
				
			||||||
 | 
					me@privacy.net
 | 
				
			||||||
 | 
					admin@
 | 
				
			||||||
 | 
					daemon@
 | 
				
			||||||
 | 
					anon@
 | 
				
			||||||
 | 
					audit@
 | 
				
			||||||
 | 
					bin@
 | 
				
			||||||
 | 
					decnet@
 | 
				
			||||||
 | 
					default@
 | 
				
			||||||
 | 
					field@
 | 
				
			||||||
 | 
					guest@
 | 
				
			||||||
 | 
					hostmaster@
 | 
				
			||||||
 | 
					install@
 | 
				
			||||||
 | 
					mailer.*@
 | 
				
			||||||
 | 
					maint.*@
 | 
				
			||||||
 | 
					news@
 | 
				
			||||||
 | 
					newsmaster@
 | 
				
			||||||
 | 
					nobody@
 | 
				
			||||||
 | 
					operator@
 | 
				
			||||||
 | 
					postmaster@
 | 
				
			||||||
 | 
					root@
 | 
				
			||||||
 | 
					shutdown@
 | 
				
			||||||
 | 
					sync@
 | 
				
			||||||
 | 
					sys@
 | 
				
			||||||
 | 
					sysop@
 | 
				
			||||||
 | 
					system@
 | 
				
			||||||
 | 
					test@
 | 
				
			||||||
 | 
					tutor@
 | 
				
			||||||
 | 
					usenet@
 | 
				
			||||||
 | 
					uucp@ 
 | 
				
			||||||
							
								
								
									
										194
									
								
								messages.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								messages.cfg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,194 @@
 | 
				
			||||||
 | 
					# Messages used in Usevote. Variables are enclosed in ${... }.
 | 
				
			||||||
 | 
					# Mostly these is interactive output for the votetaker, but texts from
 | 
				
			||||||
 | 
					# uvbounce.pl and uvrules.pl are also partly mailed back to the voters.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Comments are allowed, but the # sign must be at the beginning of the line
 | 
				
			||||||
 | 
					# (no leading spaces or others characters allowed).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# General format:
 | 
				
			||||||
 | 
					# Identifier = message
 | 
				
			||||||
 | 
					# (Identifier has to start at the beginning of the line, without leading space)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					###################################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# UVconfig.pm
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					CONF_NOGROUPS = Kein Abstimmungsgegenstand definiert (siehe ${CONFIGFILE})!
 | 
				
			||||||
 | 
					CONF_NOBDSGFILE = Datei mit Datenschutzhinweis ("${BDSGFILE}") nicht lesbar!
 | 
				
			||||||
 | 
					CONF_NOSIG = Abschnitt [Signatur] nicht in Datei ${FILE} gefunden!
 | 
				
			||||||
 | 
					CONF_NOBADADDR = Datei mit verdaechtigen Adressen "${BADADDRFILE}" nicht lesbar!
 | 
				
			||||||
 | 
					CONF_TEST_RULES = Regeln aus usevote.rul: 
 | 
				
			||||||
 | 
					CONF_NO_RULES = (keine Regeln definiert)
 | 
				
			||||||
 | 
					CONF_CONFIG = Konfiguration:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# UVmenu.pm
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					MENU_INVALIDNAME = Ungueltiger Name.
 | 
				
			||||||
 | 
					MENU_NONAME = Kein Name angegeben.
 | 
				
			||||||
 | 
					MENU_INVALIDBDSG = Datenschutzhinweis fehlerhaft oder nicht bestaetigt.
 | 
				
			||||||
 | 
					MENU_DUPLICATEVOTE = Doppelte Stimmabgabe gefunden.
 | 
				
			||||||
 | 
					MENU_NOVOTE = Keine Stimmabgabe gefunden.
 | 
				
			||||||
 | 
					MENU_INVALIDVOTE = Ungueltige Stimmabgabe.
 | 
				
			||||||
 | 
					MENU_NOBALLOTID = Keine Scheinkennung gefunden.
 | 
				
			||||||
 | 
					MENU_WRONGBALLOTID = Scheinkennung falsch.
 | 
				
			||||||
 | 
					MENU_ADDRESSNOTREGISTERED = Adresse nicht registriert.
 | 
				
			||||||
 | 
					MENU_INVALIDADDRESS = Ungueltige Mail-Adresse.
 | 
				
			||||||
 | 
					MENU_INVALIDADDRESS2 = Es wird keine Mail verschickt!
 | 
				
			||||||
 | 
					MENU_SUSPICIOUSACCOUNT = Verdaechtige Adresse gefunden.
 | 
				
			||||||
 | 
					MENU_UNRECOGNIZEDVOTE = Stimmen nicht vollstaendig erkannt. Im Zweifelsfall "Enthaltung" angenommen.
 | 
				
			||||||
 | 
					MENU_UNRECOGNIZED_LIST = Stimme
 | 
				
			||||||
 | 
					MENU_VIOLATEDRULE = Regel ${RULE} verletzt.
 | 
				
			||||||
 | 
					MENU_PROBLEMS = Die folgenden Probleme muessen beseitigt werden:
 | 
				
			||||||
 | 
					MENU_CAPTION = Auswahlmenue:
 | 
				
			||||||
 | 
					MENU_SHOW_MAIL = Anzeigen der Wahlmail
 | 
				
			||||||
 | 
					MENU_CHANGE_PROPERTIES = Bestaetigen oder Aendern von Wahlschein-Eigenschaften:
 | 
				
			||||||
 | 
					MENU_ADDRESS = Mailadresse
 | 
				
			||||||
 | 
					MENU_ADDRESS_CHANGE = Adresse aendern
 | 
				
			||||||
 | 
					MENU_ADDRESS_OK = Adresse OK
 | 
				
			||||||
 | 
					MENU_ADDRESS_INVALID = Adresse ungueltig
 | 
				
			||||||
 | 
					MENU_ADDRESS_PROMPT = Waehleradresse:
 | 
				
			||||||
 | 
					MENU_NAME = Waehlername
 | 
				
			||||||
 | 
					MENU_NAME_CHANGE = Namen aendern
 | 
				
			||||||
 | 
					MENU_NAME_OK = Name OK
 | 
				
			||||||
 | 
					MENU_NAME_INVALID = Name ungueltig
 | 
				
			||||||
 | 
					MENU_VOTES = Stimmen
 | 
				
			||||||
 | 
					MENU_VOTES_RESET = Stimmen neu setzen
 | 
				
			||||||
 | 
					MENU_VOTES_OK = Stimmen OK
 | 
				
			||||||
 | 
					MENU_VOTES_INVALID = Stimmen ungueltig
 | 
				
			||||||
 | 
					MENU_VOTES_CANCELLED = Stimmen vom Waehler annulliert
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER = Stimme fuer ${GROUP} (J, N oder E): 
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER_ASK = Bitte die Stimmen neu eingeben. Die aus dem Wahlschein erkannten Stimmen sind jeweils der Standardwert und werden in [ ] aufgefuehrt.
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER_LEGEND = J: Ja | N: Nein | E: Enthaltung
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER_OLD = Bisherige Stimmen:
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER_NEW = Neue Stimmen:
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER_ACK = Stimmen uebernehmen
 | 
				
			||||||
 | 
					MENU_VOTES_REENTER_NACK = bisherige Stimmen belassen
 | 
				
			||||||
 | 
					MENU_BALLOT_ID = Scheinkennung
 | 
				
			||||||
 | 
					MENU_BDSG = Datenschutzklausel
 | 
				
			||||||
 | 
					MENU_BDSG_ACCEPTED = Datenschutzklausel wurde akzeptiert
 | 
				
			||||||
 | 
					MENU_BDSG_DECLINED = Datenschutzklausel nicht akzeptiert bzw. Text veraendert
 | 
				
			||||||
 | 
					MENU_IGNORE = Diese Stimme ignorieren (ohne Benachrichtigung verwerfen)
 | 
				
			||||||
 | 
					MENU_IGNORE_WARNING = Die Stimme wird nicht aufgezeichnet, und es wird keine Bestaetigung verschickt. ${MENU_IGNORE_STRING} eingeben, wenn Du sicher bist: 
 | 
				
			||||||
 | 
					MENU_IGNORE_STRING = JA
 | 
				
			||||||
 | 
					MENU_PROCEED = Weiter
 | 
				
			||||||
 | 
					MENU_PROMPT = Eingabe: 
 | 
				
			||||||
 | 
					MENU_GETKEY = *** Return druecken, um fortzufahren ***
 | 
				
			||||||
 | 
					MENU_PROCESSING = Verarbeite Mails...
 | 
				
			||||||
 | 
					MENU_ERROR_WARNING = WARNUNG
 | 
				
			||||||
 | 
					MENU_ERROR_TEXT = Es wurden nicht alle Fehler behoben. Der Waehler wird eine Fehlermail erhalten und die Stimme wird ungueltig gewertet.
 | 
				
			||||||
 | 
					MENU_ERROR_GETKEY = Bitte mit 'y' bestätigen oder mit jeder anderen Eingabe zurück: 
 | 
				
			||||||
 | 
					MENU_DUP_VOTE = Moeglicherweise doppelte Stimmabgabe!
 | 
				
			||||||
 | 
					MENU_DUP_FIRST = Erste Stimme:
 | 
				
			||||||
 | 
					MENU_DUP_SECOND = Zweite Stimme:
 | 
				
			||||||
 | 
					MENU_DUP_DELFIRST = Erste loeschen
 | 
				
			||||||
 | 
					MENU_DUP_DELSECOND = Zweite loeschen
 | 
				
			||||||
 | 
					MENU_DUP_DELNONE = Keine loeschen
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# UVreadmail.pm
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					READMAIL_STATUS = Abruf neuer Mails vom POP3-Server...
 | 
				
			||||||
 | 
					READMAIL_NOCONNECTION = Verbindung zum POP3-Server fehlgeschlagen!
 | 
				
			||||||
 | 
					READMAIL_NOLOGIN = Anmeldung am POP3-Server nicht moeglich!
 | 
				
			||||||
 | 
					READMAIL_NOMAILFILE = Maildatei ${FILE} nicht lesbar!
 | 
				
			||||||
 | 
					READMAIL_GET_PROBLEM = Warnung! Konnte Mail Nr. ${NR} nicht abrufen.
 | 
				
			||||||
 | 
					READMAIL_DEL_PROBLEM = Warnung! Konnte Mail Nr. ${NR} nicht loeschen.
 | 
				
			||||||
 | 
					READMAIL_UIDL_PROBLEM = Warnung! Konnte Liste mit UIDLs nicht speichern.
 | 
				
			||||||
 | 
					READMAIL_UIDL_PROBLEM2 = Beim naechsten Lauf keine Erkennung bereits abgerufener Mails moeglich!
 | 
				
			||||||
 | 
					READMAIL_UIDL_CLOSE = Warnung! Konnte UIDL-Cachedatei nicht ordnungsgemaess schliessen.
 | 
				
			||||||
 | 
					READMAIL_ARCHIVE_PROBLEM = Warnung! Wahlmails konnten nicht in Datei ${FILE} gesichert werden.
 | 
				
			||||||
 | 
					READMAIL_ARCHIVE_CLOSE = Warnung! Konnte Wahlmail-Archivdatei ${FILE} nicht schliessen.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# UVrules.pm
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					RULES_ERROPENFILE = Kann Regeldatei ${FILE} nicht oeffnen
 | 
				
			||||||
 | 
					RULES_TOOSHORT = Regel ${NUM}: '${TYPE}'-Bedingung zu kurz
 | 
				
			||||||
 | 
					RULES_TOOLONG = Regel ${NUM}: '${TYPE}'-Bedingung zu lang
 | 
				
			||||||
 | 
					RULES_INVCHARS = Regel ${NUM}: '${TYPE}'-Bedingung enthaelt nicht erlaubte Zeichen
 | 
				
			||||||
 | 
					RULES_RULE = Wahlregel
 | 
				
			||||||
 | 
					RULES_IF = Wenn Du
 | 
				
			||||||
 | 
					RULES_THEN = musst Du
 | 
				
			||||||
 | 
					RULES_AND = und
 | 
				
			||||||
 | 
					RULES_OR = oder
 | 
				
			||||||
 | 
					RULES_YES = JA
 | 
				
			||||||
 | 
					RULES_NO = NEIN
 | 
				
			||||||
 | 
					RULES_ABSTAIN = ENTHALTUNG
 | 
				
			||||||
 | 
					RULES_IFCLAUSE = ${VOTE} stimmst fuer ${GROUP}
 | 
				
			||||||
 | 
					RULES_THENCLAUSE = ${VOTE} stimmen fuer ${GROUP}
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# UVsendmail.pm
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					SENDMAIL_ERROPENCONTROL = FEHLER! Steuerungsdatei ${FILE} konnte nicht geoeffnet werden.
 | 
				
			||||||
 | 
					SENDMAIL_ERRCLOSECONTROL = FEHLER! Steuerungsdatei ${FILE} konnte nicht geschlossen werden.
 | 
				
			||||||
 | 
					SENDMAIL_ERRDELCONTROL = FEHLER! Steuerungsdatei ${FILE} konnte nicht geloescht werden.
 | 
				
			||||||
 | 
					SENDMAIL_ERROPENMAIL = FEHLER! Mail-Datei ${FILE} konnte nicht geoeffnet werden.
 | 
				
			||||||
 | 
					SENDMAIL_ERRCLOSEMAIL = FEHLER! Mail-Datei ${FILE} konnte nicht geschlossen werden.
 | 
				
			||||||
 | 
					SENDMAIL_NOMAILS = Keine Mails zu verschicken (Datei ${FILE} nicht gefunden).
 | 
				
			||||||
 | 
					SENDMAIL_SMTP_CONNREFUSED = Keine Verbindung zum SMTP-Server moeglich!
 | 
				
			||||||
 | 
					SENDMAIL_SMTP_AUTHERR = Anmeldung am SMTP-Server fehlgeschlagen!
 | 
				
			||||||
 | 
					SENDMAIL_ERRNOTFOUND = Datei ${FILE} nicht gefunden.
 | 
				
			||||||
 | 
					SENDMAIL_SMTP_INVRCPT = Mail an ${RCPT} konnte nicht verschickt werden:
 | 
				
			||||||
 | 
					SENDMAIL_SENDING = Mails werden verschickt...
 | 
				
			||||||
 | 
					SENDMAIL_ERROCCURED = Fehler aufgetreten. Bitte kontrollieren und "uvvote.pl clean" ggf. noch einmal starten!
 | 
				
			||||||
 | 
					SENDMAIL_MISSINGFILES = Dateien konnten nicht gefunden werden. Dieser Fehler kann auftreten, falls bei einem vorherigen Lauf nur einzelne Mails verschickt werden konnten (diese Dateien wurden dann bereits geloescht).
 | 
				
			||||||
 | 
					SENDMAIL_ERRCLOSEDOMAIL = FEHLER! domail-Datei konnte nicht geschlossen werden.
 | 
				
			||||||
 | 
					SENDMAIL_ACKTXT_MISSING = KONFIGURATIONSFEHLER: Abschnitt [${SECTION}] in ${FILE} existiert nicht! Mails an die Waehler sind moeglicherweise unvollstaendig.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# uvballot.pl
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					BALLOT_NO_PERSONAL = Die Option -t kann nur in Zusammenhang mit persoenlichen Wahlscheinen verwendet werden (Option "personal" in ${CFGFILE}).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# uvbounce.pl
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					BOUNCE_BALLOT = ! Wahlschein nicht zustellbar (Adresse ungueltig)
 | 
				
			||||||
 | 
					BOUNCE_ACKMAIL = ! Bestaetigung nicht zustellbar (Adresse ungueltig)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# uvcfv.pl
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					CFV_NUMBER = Es werden ${COUNT} CfVs verschickt.
 | 
				
			||||||
 | 
					CFV_ERRWRITE = Kann nicht in Scheinkennungsdatei ${FILE} schreiben!
 | 
				
			||||||
 | 
					CFV_ERRCLOSE = Kann Scheinkennungsdatei nicht schliessen!
 | 
				
			||||||
 | 
					CFV_ERROPENCFV = Kann CfV-Datei ${FILE} nicht lesen!
 | 
				
			||||||
 | 
					CFV_SUBJECT = Wahlschein
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# uvcount.pl
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					COUNT_ERR_OPEN = Kann Ergebnisdatei ${FILE} nicht oeffnen!
 | 
				
			||||||
 | 
					COUNT_ERR_RESULT = Fehler in ${FILE} Zeile ${LINE}
 | 
				
			||||||
 | 
					COUNT_ERR_GROUPCOUNT = Bei Stimme von <${ADDR}>: ${NUM1} statt ${NUM2} Stimmen gefunden (${RESULTFILE} kontrollieren!)
 | 
				
			||||||
 | 
					COUNT_DELETED = ${NUM} Stimme(n) geloescht.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# uvvote.pl
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					VOTE_RENAMING_MAILBOX = Benenne Stimmdatei um...
 | 
				
			||||||
 | 
					VOTE_WRITE_RESULTS = Ergebnisdatei ${FILE} nicht schreibbar!
 | 
				
			||||||
 | 
					VOTE_CLOSE_RESULTS = Ergebnisdatei ${FILE} konnte nicht erfolgreich geschlossen werden!
 | 
				
			||||||
 | 
					VOTE_NO_VOTES = Keine Stimmen zu verarbeiten.
 | 
				
			||||||
 | 
					VOTE_NUM_VOTES = ${COUNT} Stimmen bearbeitet.
 | 
				
			||||||
 | 
					VOTE_NOT_SAVED = ${COUNT} Stimmen bearbeitet, aber nicht gespeichert.
 | 
				
			||||||
 | 
					VOTE_FIRSTRUN = 'uvvote clean' aufrufen, um Ergebnisse zu speichern und Bestaetigungen zu verschicken.
 | 
				
			||||||
 | 
					VOTE_ERRORS = Folgende Fehler sind aufgetreten (siehe auch ${FILE}):
 | 
				
			||||||
 | 
					VOTE_INVALID_BALLOTID = Scheinkennung ungueltig
 | 
				
			||||||
 | 
					VOTE_MISSING_BALLOTID = Scheinkennung fehlt
 | 
				
			||||||
 | 
					VOTE_UNREGISTERED_ADDRESS = Adresse nicht registriert
 | 
				
			||||||
 | 
					VOTE_INVALID_VOTE = Ungueltige Stimmabgabe
 | 
				
			||||||
 | 
					VOTE_VIOLATED_RULE = Regel ${RULE} verletzt
 | 
				
			||||||
 | 
					VOTE_NO_VOTES = Keine Stimmen abgegeben
 | 
				
			||||||
 | 
					VOTE_INVALID_ACCOUNT = Ungueltiger Account
 | 
				
			||||||
 | 
					VOTE_INVALID_ADDRESS = Ungueltige Adresse
 | 
				
			||||||
 | 
					VOTE_INVALID_REALNAME = Ungueltiger Realname
 | 
				
			||||||
 | 
					VOTE_MISSING_NAME = Kein Name angegeben
 | 
				
			||||||
 | 
					VOTE_DUPLICATES = Verschiedene Stimmen fuer gleichen Abstimmungspunkt
 | 
				
			||||||
 | 
					VOTE_FILE_COMMENT = Wahlleiter setzte ${FIELDS}
 | 
				
			||||||
 | 
					VOTE_NO_NEW_RESULTS = Keine noch nicht verarbeiteten Ergebnisdateien gefunden! Bitte uvvote.pl zunaechst ohne die 'clean'-Option starten.
 | 
				
			||||||
 | 
					VOTE_MOVE_RESULTFILE = Fehler! Konnte Ergebnisdatei ${FILE} nicht verschieben: 
 | 
				
			||||||
 | 
					VOTE_MOVE_VOTEFILE = Fehler! Konnte Stimmdatei ${FILE} nicht verschieben: 
 | 
				
			||||||
 | 
					VOTE_CREATING_RESULTS = Erstelle neue Gesamtergebnisdatei ${FILENAME}...
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Allgemeine Meldungen
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					ERR_MKDIR = Kann Verzeichnis '${DIR}' nicht anlegen: 
 | 
				
			||||||
 | 
					ERR_NOTPERSONAL = Usevote ist nicht fuer die Verwendung personalisierter Wahlscheine konfiguriert (Option "personal" in ${CFGFILE})
 | 
				
			||||||
 | 
					ERR_FILE_CREATION = Fataler Fehler: Konnte keine Datei anlegen.
 | 
				
			||||||
 | 
					ERR_RENAME_MAILFILE = Konnte Maildatei nicht umbenennen: 
 | 
				
			||||||
 | 
					ERR_LOCK = Lockfile ${FILE} bereits vorhanden! Wurde UseVoteGer mehrfach gestartet?
 | 
				
			||||||
 | 
					INFO_TIDY_UP = Aufraeumen...
 | 
				
			||||||
							
								
								
									
										46
									
								
								templates/ack-mail
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								templates/ack-mail
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					ballotid-line   := value ballotidtext | fill-right 20 | append ballotid
 | 
				
			||||||
 | 
					address-line    := value addresstext | fill-right 20 | append address
 | 
				
			||||||
 | 
					name-line       := value nametext2 | fill-right 20 | append name
 | 
				
			||||||
 | 
					pos             := value pos | fill-right 2
 | 
				
			||||||
 | 
					group-first 	:= value group | first-words 50 
 | 
				
			||||||
 | 
					group-more  	:= value group | drop-words 50 | create-lines 50
 | 
				
			||||||
 | 
					vote            := value vote  | fill-both 10
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Diese automatische Nachricht wurde dir nach Zaehlung deiner Stimme
 | 
				
			||||||
 | 
					zugesandt. Wenn alles stimmt, gibt es keinen Anlass fuer eine Reaktion.
 | 
				
			||||||
 | 
					Wenn deine Stimme falsch registriert wurde, stimme bitte erneut ab,
 | 
				
			||||||
 | 
					indem du diese Mail komplett zitierst und die falschen Wertungen
 | 
				
			||||||
 | 
					korrigierst (zwischen die eckigen Klammern schreiben). Dabei darf
 | 
				
			||||||
 | 
					keinesfalls die laufende Nummer am Zeilenanfang entfernt werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Diese Wahl ist oeffentlich, und die Adressen aller Waehlerinnen und
 | 
				
			||||||
 | 
					Waehler werden am Ende bekanntgegeben. Wenn du deine Adresse & Stimme
 | 
				
			||||||
 | 
					loeschen willst, kannst du erneut abstimmen und dabei 'ANNULLIERUNG'
 | 
				
			||||||
 | 
					anstelle von 'JA' oder 'NEIN' angeben. \[Doppel-N, Doppel-L :-)\]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[?personal|Da diese Abstimmung mit personalisierten Wahlscheinen durchgefuehrt
 | 
				
			||||||
 | 
					wird, sind auch saemtliche Aenderungen nur mit Angabe der folgenden
 | 
				
			||||||
 | 
					Wahlscheinkennung gueltig!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$ballotid-line]]
 | 
				
			||||||
 | 
					[$address-line]
 | 
				
			||||||
 | 
					[$name-line]
 | 
				
			||||||
 | 
					  (Real-Namen sind fuer diese Abstimmung vorgeschrieben. Wenn hier
 | 
				
			||||||
 | 
					   nicht Dein wirklicher Name steht, dann korrigiere die Zeile
 | 
				
			||||||
 | 
					   bitte und sende die Nachricht zurueck; sonst kann die Stimme
 | 
				
			||||||
 | 
					   spaeter als ungueltig gewertet werden.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Deine Stimmabgabe wurde wie folgt erkannt:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[@groups|#[$pos]  \[[$vote]\]  fuer [$group-first]
 | 
				
			||||||
 | 
					[@group-more|                        [$line]\n]|\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Danke fuer deine Stimmabgabe.  Eine Kopie des CfV kannst du von mir er-
 | 
				
			||||||
 | 
					halten (bitte Namen der Abstimmung angeben, falls mehrere laufen).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										25
									
								
								templates/address-not-registered
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								templates/address-not-registered
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					head            := value head     | quote "> "
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Deine Adresse ist beim Wahlleiter bisher nicht mit einer Wahlschein-
 | 
				
			||||||
 | 
					kennung registriert, mit einer EMail an die im CfV genannten Adresse
 | 
				
			||||||
 | 
					kannst du dir eine Kennung zuteilen lassen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Solltest du bereits eine Kennung erhalten haben, so achte bitte darauf,
 | 
				
			||||||
 | 
					diese nur mit genau der Mailadresse zu verwenden, fuer die sie
 | 
				
			||||||
 | 
					registriert ist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Achtung, die Mailadresse wird unter Beachtung von Gross- und Klein-
 | 
				
			||||||
 | 
					schreibung ausgewertet, Meier und meier sind daher _nicht_ identisch!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$head]
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										34
									
								
								templates/ballot
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								templates/ballot
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					votename-first  := value votename | first-words 55
 | 
				
			||||||
 | 
					votename-more   := value votename | drop-words 55 | create-lines 55
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pos             := value pos | fill-right 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					group-first 	:= value group | first-words 50 
 | 
				
			||||||
 | 
					group-more  	:= value group | drop-words 50 | create-lines 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bdsginfo        := value bdsginfo | create-lines 72
 | 
				
			||||||
 | 
					bdsgtext-first  := value bdsgtext | first-words 50
 | 
				
			||||||
 | 
					bdsgtext-more   := value bdsgtext | drop-words 50 | create-lines 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=-=-=-=-=-=-=-=- Alles vor dieser Zeile bitte loeschen =-=-=-=-=-=-=-=-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WAHLSCHEIN fuer [$votename-first]
 | 
				
			||||||
 | 
					[@votename-more|                [$line]\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$nametext]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wenn du keinen Real-Namen angibst, wird deine Stimme fuer
 | 
				
			||||||
 | 
					ungueltig erklaert werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nr   \[Deine Stimme\]  Gruppe/Abstimmungsgegenstand
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					[@groups|#[$pos]  \[            \]  [$group-first]
 | 
				
			||||||
 | 
					[@group-more|                     [$line]\n]|\n]
 | 
				
			||||||
 | 
					[?bdsg|[@bdsginfo|[$line]|\n]\n\n#a   \[            \]  [$bdsgtext-first]
 | 
				
			||||||
 | 
					[@bdsgtext-more|                     [$line]|\n]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=-=-=-=-=-=-=-=- Alles nach dieser Zeile bitte loeschen =-=-=-=-=-=-=-=-
 | 
				
			||||||
							
								
								
									
										63
									
								
								templates/ballot-personal
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								templates/ballot-personal
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,63 @@
 | 
				
			||||||
 | 
					votename-first  := value votename | first-words 55
 | 
				
			||||||
 | 
					votename-more   := value votename | drop-words 55 | create-lines 55
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pos             := value pos | fill-right 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					group-first 	:= value group | first-words 50 
 | 
				
			||||||
 | 
					group-more  	:= value group | drop-words 50 | create-lines 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bdsginfo        := value bdsginfo | create-lines 72
 | 
				
			||||||
 | 
					bdsgtext-first  := value bdsgtext | first-words 50
 | 
				
			||||||
 | 
					bdsgtext-more   := value bdsgtext | drop-words 50 | create-lines 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[?alreadysent|
 | 
				
			||||||
 | 
					!! Dieser CfV wurde dir bereits einmal zugeschickt, sollte der erste
 | 
				
			||||||
 | 
					!! Wahlschein nicht angekommen oder die Anforderung nicht auf deinen
 | 
				
			||||||
 | 
					!! Wunsch geschehen sein, so wende dich bitte an den Wahlleiter.
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					************************************
 | 
				
			||||||
 | 
					*** hier den CfV-Text einfuegen! ***
 | 
				
			||||||
 | 
					************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=-=-=-=-=-=-=-=- Alles vor dieser Zeile bitte loeschen =-=-=-=-=-=-=-=-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WAHLSCHEIN fuer [$votename-first]
 | 
				
			||||||
 | 
					[@votename-more|                [$line]\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$ballotidtext] [$ballotid]
 | 
				
			||||||
 | 
					[$addresstext] [$address]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dies ist deine persoenliche und _geheime_ Wahlschein-Kennung!
 | 
				
			||||||
 | 
					Halte deine Wahlscheinkennung zwecks Missbrauchs- und Manipulations-
 | 
				
			||||||
 | 
					vermeidung bitte moeglichst geheim, da jeder, der sie kennt, in
 | 
				
			||||||
 | 
					deinem Namen abstimmen kann!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$nametext]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wenn du keinen Real-Namen angibst, wird deine Stimme fuer
 | 
				
			||||||
 | 
					ungueltig erklaert werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nr   \[Deine Stimme\]  Gruppe/Abstimmungsgegenstand
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					[@groups|#[$pos]  \[            \]  [$group-first]
 | 
				
			||||||
 | 
					[@group-more|                     [$line]\n]|\n]
 | 
				
			||||||
 | 
					[?bdsg|[@bdsginfo|[$line]|\n]\n\n#a   \[            \]  [$bdsgtext-first]
 | 
				
			||||||
 | 
					[@bdsgtext-more|                     [$line]|\n]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=-=-=-=-=-=-=-=- Alles nach dieser Zeile bitte loeschen =-=-=-=-=-=-=-=-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Danke fuer Deine Stimmabgabe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										10
									
								
								templates/ballot-request
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								templates/ballot-request
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					=-=-=-=-=-=-=-=- Alles vor dieser Zeile bitte loeschen =-=-=-=-=-=-=-=-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zur Wahlscheinanforderung einfach formlos *per Mail* auf dieses
 | 
				
			||||||
 | 
					Posting antworten. Falls nach einigen Tagen noch kein Wahlschein
 | 
				
			||||||
 | 
					eingetroffen ist, kannst du unter folgender Adresse mit dem
 | 
				
			||||||
 | 
					Wahlleiter Kontakt aufnehmen:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$mailaddress]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=-=-=-=-=-=-=-=- Alles nach dieser Zeile bitte loeschen =-=-=-=-=-=-=-=-
 | 
				
			||||||
							
								
								
									
										29
									
								
								templates/bdsg-error
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								templates/bdsg-error
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,29 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Zur Wertung deiner Stimme ist die Zustimmung zur Speicherung,
 | 
				
			||||||
 | 
					Verarbeitung und Veroeffentlichung der Stimmabgabe erforderlich.
 | 
				
			||||||
 | 
					Diese Zustimmung konnte nicht automatisch erkannt werden.
 | 
				
			||||||
 | 
					deine Stimme wurde daher geloescht und wird nicht gewertet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dieses kann folgende Gruende haben:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* In deinem Wahlschein fehlt der Abschnitt, der ueber die Art
 | 
				
			||||||
 | 
					  der Verarbeitung deiner Stimmdaten informiert, oder er wurde
 | 
				
			||||||
 | 
					  als nicht vollstaendig erkannt. Um bezueglich des deutschen
 | 
				
			||||||
 | 
					  Bundesdatenschutzgesetzes keine Risiken einzugehen, muss ich
 | 
				
			||||||
 | 
					  darauf bestehen, dass dieser Absatz unveraendert mitgeschickt
 | 
				
			||||||
 | 
					  und akzeptiert wird.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Du hast nicht der Speicherung/Verarbeitung/Veroeffentlichung
 | 
				
			||||||
 | 
					  zugestimmt. Im dazugehoerigen Feld muss "JA" eingetragen
 | 
				
			||||||
 | 
					  werden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bitte stimme erneut ab, lasse dabei den Hinweistext im
 | 
				
			||||||
 | 
					Wahlschein intakt und akzeptiere die Klausel, indem du im
 | 
				
			||||||
 | 
					vorgesehen Feld "JA" eintraegst. Sollte das Problem aufgrund eines
 | 
				
			||||||
 | 
					Uebermittlungsfehlers bestehen bleiben, melde Dich bitte unter
 | 
				
			||||||
 | 
					der unten angegebenen Adresse bei mir.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										10
									
								
								templates/bouncelist
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								templates/bouncelist
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					multi-line 	:= value name | justify-before mail 72
 | 
				
			||||||
 | 
					bouncetext      := value bouncetext | create-lines 72
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Als ungueltig erkannte Stimmen:
 | 
				
			||||||
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 | 
					[@bounces|[$multi-line]
 | 
				
			||||||
 | 
					[@bouncetext|[$line]]|\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								templates/cancelled
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								templates/cancelled
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Diese automatische Nachricht wurde dir nach Erhalt Deiner ANNULLIERUNG
 | 
				
			||||||
 | 
					zugesandt. Jede vorherige Stimmabgabe in dieser Abstimmung ist dadurch
 | 
				
			||||||
 | 
					annulliert und wird weder gezaehlt noch veroeffentlicht.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wenn dies ein Fehler war und du doch waehlen moechtest, musst du erneut
 | 
				
			||||||
 | 
					abstimmen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										27
									
								
								templates/invalid-account
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								templates/invalid-account
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					head            := value head     | quote "> "
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Deine Stimme kann nicht akzeptiert werden, da du eine kritische
 | 
				
			||||||
 | 
					Absenderadresse verwendest. Nichtpersoenliche Accounts wie root@,
 | 
				
			||||||
 | 
					operator@, postmaster@, guest@ usw. sind im Allgemeinen nicht zu
 | 
				
			||||||
 | 
					Abstimmungen zugelassen, insbesondere, wenn kein Realname angegeben
 | 
				
			||||||
 | 
					wird. Stimmen von Anon-Servern werden ebenfalls nicht akzeptiert.
 | 
				
			||||||
 | 
					Bitte stimme erneut von einem persoenlichen Account aus ab.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wenn das ein Fehler ist und dein wahrer Name/Account faelschlicherweise
 | 
				
			||||||
 | 
					fuer einen dieser unpersoenlichen oder Anon-Accounts gehalten wurde, so
 | 
				
			||||||
 | 
					schicke bitte eine eMail an meine persoenliche Adresse. Sorry fuer das
 | 
				
			||||||
 | 
					umstaendliche Verfahren, aber nur so ist die zuverlaessige automatische
 | 
				
			||||||
 | 
					Stimmenzaehlung moeglich.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhielt:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$head]
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										19
									
								
								templates/invalid-name
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								templates/invalid-name
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					head            := value head     | quote "> "
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Dieser Call for Votes (CfV) erfordert die Angabe eines Real-Namens ent-
 | 
				
			||||||
 | 
					weder im "From:"-Feld des Headers oder im dafuer vorgesehehen Feld des
 | 
				
			||||||
 | 
					Wahlscheins. Bitte wiederhole Deine Stimmabgabe mit Angabe Deines wirk-
 | 
				
			||||||
 | 
					lichen Namens.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$head]
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										16
									
								
								templates/mailheader
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								templates/mailheader
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					date := generate-date-header
 | 
				
			||||||
 | 
					msgid := generate-msgid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					From: [$from]
 | 
				
			||||||
 | 
					Subject: [$subject]
 | 
				
			||||||
 | 
					To: [$address]
 | 
				
			||||||
 | 
					[?reply-to|Reply-To: [$reply-to]]
 | 
				
			||||||
 | 
					[?reference|In-Reply-To: [$reference]]
 | 
				
			||||||
 | 
					[?reference|References: [$reference]]
 | 
				
			||||||
 | 
					Message-ID: [$msgid]
 | 
				
			||||||
 | 
					Date: [$date]
 | 
				
			||||||
 | 
					X-Automated-Message: generated by [$usevote-version]
 | 
				
			||||||
 | 
					MIME-Version: 1.0
 | 
				
			||||||
 | 
					Content-Type: text/plain; charset\=iso-8859-1
 | 
				
			||||||
 | 
					Content-Transfer-Encoding: 8bit
 | 
				
			||||||
							
								
								
									
										19
									
								
								templates/multiple-votes
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								templates/multiple-votes
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Dein Wahlschein enthielt widerspruechliche Stimmen (z.B. sowohl JA- als
 | 
				
			||||||
 | 
					auch NEIN-Stimme fuer dieselbe Gruppe).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Das passiert meistens, wenn du mehrere Zeilen schickst,  die als Stimme
 | 
				
			||||||
 | 
					interpretiert werden, z. B. wenn du vergisst, eine Beispielzeile im CfV
 | 
				
			||||||
 | 
					zu loeschen. Bitte lies den CfV noch einmal und wiederhole deine Stimm-
 | 
				
			||||||
 | 
					abgabe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										16
									
								
								templates/no-ballot
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								templates/no-ballot
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					In deiner Mail wurde kein gueltiger Wahlschein gefunden. Bitte lies die
 | 
				
			||||||
 | 
					Hinweise im Call for Votes (CfV) und stimme nochmal ab.
 | 
				
			||||||
 | 
					Dieser Fehler tritt meistens dann auf, wenn du Zeilen loeschst, die du
 | 
				
			||||||
 | 
					laut CfV nicht haettest loeschen sollen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										19
									
								
								templates/no-ballotid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								templates/no-ballotid
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					head            := value head     | quote "> "
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					In deinem Wahlschein konnte keine Wahlscheinkennung gefunden werden,
 | 
				
			||||||
 | 
					diese wurde dir zusammen mit dem Wahlschein zugeschickt. Solltest
 | 
				
			||||||
 | 
					du noch keine eigenen Wahlscheinkennung haben, so kannst du mit
 | 
				
			||||||
 | 
					einer Mail an die im CfV genannte Adresse eine anfordern.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$head]
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										20
									
								
								templates/no-votes
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								templates/no-votes
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Offenbar hast du keinerlei Stimmen abgegeben. Wenn das ein Irrtum war,
 | 
				
			||||||
 | 
					lies bitte nochmal die Hinweise im CfV und wiederhole Deine Stimmabgabe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dieser Fehler tritt oft auf, wenn du dich vertippst oder dich nicht an
 | 
				
			||||||
 | 
					das im Wahlschein vorgegebene Format haeltst.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wenn du dich enthalten willst, dann setze bitte ENTHALTUNG an die
 | 
				
			||||||
 | 
					Stelle von JA oder NEIN.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										31
									
								
								templates/result-multi
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								templates/result-multi
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					votename-first        := value votename | first-words 60
 | 
				
			||||||
 | 
					votename-more         := value votename | drop-words 60 | create-lines 60
 | 
				
			||||||
 | 
					numinvalid            := value numinvalid | fill-left 4
 | 
				
			||||||
 | 
					numabstain-formatted  := value numabstain | fill-left 4
 | 
				
			||||||
 | 
					yes                   := value yes | fill-left 4
 | 
				
			||||||
 | 
					no                    := value no | fill-left 4
 | 
				
			||||||
 | 
					group-first           := value group | first-words 40
 | 
				
			||||||
 | 
					group-more            := value group | drop-words 40 | create-lines 40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE ============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ergebnisse [$votename-first]
 | 
				
			||||||
 | 
					[@votename-more|           [$line]\n]
 | 
				
			||||||
 | 
					([$numvalid] gueltige Stimmen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Ja  Nein : 2/3? >=60? : ang.? : Gruppe
 | 
				
			||||||
 | 
					---- ---- : ---- ----- : ----- : ---------------------------------------
 | 
				
			||||||
 | 
					[@count|[$yes] [$no] : [?cond1| Ja |Nein] [?cond2| Ja |Nein]  : [?result| Ja |Nein]  : [$group-first]
 | 
				
			||||||
 | 
					[@group-more|          :            :       : [$line]\n]\n]
 | 
				
			||||||
 | 
					[?numabstain|[$numabstain-formatted] Enthaltungen]
 | 
				
			||||||
 | 
					[?numinvalid|[$numinvalid] ungueltige Stimme(n)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gegen dieses Ergebnis kann innerhalb einer Woche nach seiner
 | 
				
			||||||
 | 
					Veroeffentlichung Einspruch erhoben werden. Der Einspruch ist per
 | 
				
			||||||
 | 
					E-Mail bei der Moderation von de.admin.news.announce (Adressen
 | 
				
			||||||
 | 
					siehe Signatur) einzulegen.
 | 
				
			||||||
 | 
					Wenn es keine ernsthaften Einsprueche gibt oder diese abgelehnt
 | 
				
			||||||
 | 
					werden, wird die Moderation von de.admin.news.announce das
 | 
				
			||||||
 | 
					Ergebnis danach umsetzen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										31
									
								
								templates/result-proportional
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								templates/result-proportional
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					votename-first        := value votename | first-words 60
 | 
				
			||||||
 | 
					votename-more         := value votename | drop-words 60 | create-lines 60
 | 
				
			||||||
 | 
					proportion            := value proportion | sprintf '%6.3f'
 | 
				
			||||||
 | 
					numinvalid            := value numinvalid | fill-left 4
 | 
				
			||||||
 | 
					numabstain-formatted  := value numabstain | fill-left 4
 | 
				
			||||||
 | 
					yes                   := value yes | fill-left 4
 | 
				
			||||||
 | 
					no                    := value no | fill-left 4
 | 
				
			||||||
 | 
					group-first           := value group | first-words 40
 | 
				
			||||||
 | 
					group-more            := value group | drop-words 40 | create-lines 40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE ============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ergebnisse [$votename-first]
 | 
				
			||||||
 | 
					[@votename-more|           [$line]\n]
 | 
				
			||||||
 | 
					([$numvalid] gueltige Stimmen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Ja  Nein : J>=N? Ja/Nein : ang.? : Gruppe
 | 
				
			||||||
 | 
					---- ---- : ----- ------- : ----- : ---------------------------------------
 | 
				
			||||||
 | 
					[@count|[$yes] [$no] : [?cond1| Ja |Nein]  [$proportion]  :       : [$group-first]
 | 
				
			||||||
 | 
					[@group-more|          :               :       : [$line]\n]\n]
 | 
				
			||||||
 | 
					[?numinvalid|[$numinvalid] ungueltige Stimme(n)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gegen dieses Ergebnis kann innerhalb einer Woche nach seiner
 | 
				
			||||||
 | 
					Veroeffentlichung Einspruch erhoben werden. Der Einspruch ist per
 | 
				
			||||||
 | 
					E-Mail bei der Moderation von de.admin.news.announce (Adressen
 | 
				
			||||||
 | 
					siehe Signatur) einzulegen.
 | 
				
			||||||
 | 
					Wenn es keine ernsthaften Einsprueche gibt oder diese abgelehnt
 | 
				
			||||||
 | 
					werden, wird die Moderation von de.admin.news.announce das
 | 
				
			||||||
 | 
					Ergebnis danach umsetzen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								templates/result-single
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								templates/result-single
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					votename-first        := value votename | first-words 60
 | 
				
			||||||
 | 
					votename-more         := value votename | drop-words 60 | create-lines 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					votename-text-first   := value votename | first-words 30
 | 
				
			||||||
 | 
					votename-text-more    := value votename | drop-words 30 | create-lines 72
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE ============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ergebnisse [$votename-first]
 | 
				
			||||||
 | 
					[@votename-more|           [$line]\n]
 | 
				
			||||||
 | 
					([$numvalid] gueltige Stimmen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Es gab [$yes] Ja-Stimmen und [$no] Nein-Stimmen[?numabstain| bei [$numabstain] Enthaltungen].
 | 
				
			||||||
 | 
					[?numinvalid|[$numinvalid] Stimme(n) wurden als ungueltig gewertet.]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Es wurde [?cond1|die|keine] 2/3-Mehrheit erreicht und es gingen [?cond2|mehr|weniger] als
 | 
				
			||||||
 | 
					60 Ja-Stimmen ein. Damit ist die [$votename-text-first]
 | 
				
			||||||
 | 
					[@votename-text-more|[$line] |\n][?cond1|[?cond2|angenommen|abgelehnt]|abgelehnt].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gegen dieses Ergebnis kann innerhalb einer Woche nach seiner
 | 
				
			||||||
 | 
					Veroeffentlichung Einspruch erhoben werden. Der Einspruch ist per
 | 
				
			||||||
 | 
					E-Mail bei der Moderation von de.admin.news.announce (Adressen
 | 
				
			||||||
 | 
					siehe Signatur) einzulegen.
 | 
				
			||||||
 | 
					Wenn es keine ernsthaften Einsprueche gibt oder diese abgelehnt
 | 
				
			||||||
 | 
					werden, wird die Moderation von de.admin.news.announce das
 | 
				
			||||||
 | 
					Ergebnis danach umsetzen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								templates/rule-violated
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								templates/rule-violated
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Diese Abstimmung unterliegt bestimmten Bedingungen, fuer welche Gruppen
 | 
				
			||||||
 | 
					wie abgestimmt werden kann. Diese Bedingungen wurden im Call for Votes
 | 
				
			||||||
 | 
					erklaert. Deine Stimme verletzt eine oder mehrere der Regeln. Bitte lies
 | 
				
			||||||
 | 
					den CfV noch einmal durch und wiederhole Deine Stimmabgabe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die folgenden Regeln wurden nicht eingehalten:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$rules]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										12
									
								
								templates/voterlist
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								templates/voterlist
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					multi-line 	:= value name | justify-before mail 72
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE ============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Folgende Personen haben sich bislang an der Abstimmung beteiligt:
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					[@multi|[$multi-line]|\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Als ungueltig erkannte Stimmen:
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					[@invalid|[$multi-line]\n[$reason]|\n]
 | 
				
			||||||
							
								
								
									
										36
									
								
								templates/votes-multi
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								templates/votes-multi
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					grafix 		:= value group | multi-graph 72 pos groupcount
 | 
				
			||||||
 | 
					grafix-line	:= multi-line 72 groupcount
 | 
				
			||||||
 | 
					multi-line 	:= value name | append vote | justify-before mail 72
 | 
				
			||||||
 | 
					invalid-line	:= value name | justify-before mail 72
 | 
				
			||||||
 | 
					numinvalid      := value numinvalid | fill-left 4
 | 
				
			||||||
 | 
					yes		:= value yes | fill-left 4
 | 
				
			||||||
 | 
					no		:= value no | fill-left 4
 | 
				
			||||||
 | 
					condition1	:= value cond1 | fill-both 4
 | 
				
			||||||
 | 
					condition2	:= value cond2 | fill-both 5
 | 
				
			||||||
 | 
					result		:= value result | fill-both 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE ============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wichtiger Hinweis:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die unten aufgefuehrten Personen haben der Speicherung, Verarbeitung
 | 
				
			||||||
 | 
					und Veroeffentlichung ihrer Adressen und Stimmdaten nur im Rahmen dieses
 | 
				
			||||||
 | 
					Verfahrens zugestimmt. Eine Verwendung darueber hinaus wurde nicht
 | 
				
			||||||
 | 
					erlaubt. Damit ist insbesondere die Nutzung oder Uebermittlung der Daten
 | 
				
			||||||
 | 
					fuer Werbezwecke oder fuer die Markt- oder Meinungsforschung verboten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Liste der gezaehlten Stimmen:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[@groups|[$grafix]|\n]
 | 
				
			||||||
 | 
					[$grafix-line]
 | 
				
			||||||
 | 
					[@multi|[$multi-line]|\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ungueltige Stimmen:
 | 
				
			||||||
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 | 
					[@invalid|[$invalid-line]\n[$reason]|\n]
 | 
				
			||||||
							
								
								
									
										33
									
								
								templates/votes-single
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								templates/votes-single
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,33 @@
 | 
				
			||||||
 | 
					mail-name 	:= value mail | justify name 72
 | 
				
			||||||
 | 
					invalid-line	:= value name | justify-before mail 72
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE ============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wichtiger Hinweis:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Die unten aufgefuehrten Personen haben der Speicherung, Verarbeitung
 | 
				
			||||||
 | 
					und Veroeffentlichung ihrer Adressen und Stimmdaten nur im Rahmen dieses
 | 
				
			||||||
 | 
					Verfahrens zugestimmt. Eine Verwendung darueber hinaus wurde nicht
 | 
				
			||||||
 | 
					erlaubt. Damit ist insbesondere die Nutzung oder Uebermittlung der Daten
 | 
				
			||||||
 | 
					fuer Werbezwecke oder fuer die Markt- oder Meinungsforschung verboten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ja gestimmt:
 | 
				
			||||||
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 | 
					[@yes|[$mail-name]\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Nein gestimmt:
 | 
				
			||||||
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 | 
					[@no|[$mail-name]\n]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[?abstain|Enthaltung:
 | 
				
			||||||
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 | 
					[@abstain|[$mail-name]\n]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ungueltige Stimmen:
 | 
				
			||||||
 | 
					------------------------------------------------------------------------
 | 
				
			||||||
 | 
					[@invalid|[$invalid-line]\n[$reason]|\n]
 | 
				
			||||||
							
								
								
									
										23
									
								
								templates/wrong-ballotid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								templates/wrong-ballotid
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					votetaker       := value mailfrom | fill-left 65
 | 
				
			||||||
 | 
					head            := value head     | quote "> "
 | 
				
			||||||
 | 
					body            := value body     | quote "> "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					== TEMPLATE =================================================================
 | 
				
			||||||
 | 
					Die Wahlscheinkennung, die du in deinem Wahlschein benutzt hast,
 | 
				
			||||||
 | 
					entspricht nicht der Kennung, die beim Wahlleiter fuer deine EMail-
 | 
				
			||||||
 | 
					Adresse registriert ist, bitte benutzte die Wahlscheinkennung
 | 
				
			||||||
 | 
					aus deinem persoenlichen Wahlschein.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Solltest du wirklich eine andere Wahlscheinkennung zugeschickt
 | 
				
			||||||
 | 
					bekommen haben (oder du hast gar keinen Wahlschein angefordert),
 | 
				
			||||||
 | 
					so setzte dich bitte mit mir in Verbindung.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hier die Mail, die ich erhalten habe:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$head]
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
					[$body]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[$votetaker]
 | 
				
			||||||
 | 
					\[mit [$usevote_version]\]
 | 
				
			||||||
							
								
								
									
										0
									
								
								tmp/ergebnis-1191790177
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tmp/ergebnis-1191790177
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								tmp/stimmen-1191790177
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tmp/stimmen-1191790177
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								uidlcache
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								uidlcache
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										293
									
								
								usevote.cfg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								usevote.cfg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,293 @@
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					# Diese Einstellungen muessen fuer jede Abstimmung angepasst werden
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Name der Abstimmung
 | 
				
			||||||
 | 
					votename = Einrichtung von xyz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Abstimmungsgegenstaende (beliebig viele groupX moeglich,
 | 
				
			||||||
 | 
					# von 1 an durchzunummerieren)
 | 
				
			||||||
 | 
					group1 = Einrichtung von abc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Bei den folgenden Fragen bedeutet jeweils:
 | 
				
			||||||
 | 
					# 0: nein
 | 
				
			||||||
 | 
					# 1: ja
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Persoenliche Wahlscheine generieren und Scheinkennung erzwingen?
 | 
				
			||||||
 | 
					personal = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Verhaeltniswahl durchfuehren? (z.B. fuer Moderationsnachwahlen)
 | 
				
			||||||
 | 
					proportional = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Formel fuer die Berechnung des Verhaeltnisses. Kann z.B.
 | 
				
			||||||
 | 
					# $yes/$no oder $yes-$no sein, letzteres wird bei Moderationsnachwahlen
 | 
				
			||||||
 | 
					# verwendet. Als Variablen sind $yes und $no zulaessig, es kann
 | 
				
			||||||
 | 
					# beliebiger Perlcode angegeben werden, dessen Rueckgabewert im 
 | 
				
			||||||
 | 
					# Result erscheinen soll. Ausserdem wird bei der Auswertung die
 | 
				
			||||||
 | 
					# Bedingung aus "condition1" weiter unten in dieser Datei ausgewertet.
 | 
				
			||||||
 | 
					prop_formula = $yes/$no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Vote-Account (diese Adresse muss unbedingt korrekt sein, wird
 | 
				
			||||||
 | 
					# in das Reply-To uebernommen)
 | 
				
			||||||
 | 
					voteaccount = vote-xyz@foo.bar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Absender fuer den From-Header der Bestaetigungsmails
 | 
				
			||||||
 | 
					mailfrom = Vorname Nachname <gvv@foo.bar>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Absender fuer den Envelope (Return-Path) der Bestaetigungsmails
 | 
				
			||||||
 | 
					# bei Verwendung von SMTP (bitte einfach nur die Adresse eintragen,
 | 
				
			||||||
 | 
					# ohne Klammern und Zusaetze). Bei smtp=0 muss das in "mailcmd"
 | 
				
			||||||
 | 
					# eingestellt werden, z.B. "-fadresse" für Sendmail
 | 
				
			||||||
 | 
					envelopefrom = gvv@foo.bar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Nur bei persoenlichen Wahlscheinen: Datei mit Anforderungsmails
 | 
				
			||||||
 | 
					requestfile = anforderung
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datenschutzklausel generieren und auf deren Existenz pruefen?
 | 
				
			||||||
 | 
					# Konfiguration siehe unten (bdsgtext)
 | 
				
			||||||
 | 
					bdsg = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Reply-To beachten?
 | 
				
			||||||
 | 
					# Nicht empfohlen, da jemand fuer andere Personen abstimmen und
 | 
				
			||||||
 | 
					# die Bestaetigungen zu sich umlenken koennte.
 | 
				
			||||||
 | 
					replyto = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Stimmen einzeln bestaetigen? Empfohlen!
 | 
				
			||||||
 | 
					voteack = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Bcc-Adresse fuer alle Mails (Backup fuer alle Faelle)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#mailcc = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Alles in einem Schritt durchfuehren (gesonderter Aufruf von
 | 
				
			||||||
 | 
					# "uvvote.pl clean" entfaellt)? Fuehrt zu geringeren
 | 
				
			||||||
 | 
					# Eingreifmoeglichkeiten! (Mails werden automatisch verschickt)
 | 
				
			||||||
 | 
					onestep = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Fuer das Ergebnis (xx Ja-Stimmen, xx Nein-Stimmen, xx Enthaltungen)
 | 
				
			||||||
 | 
					# auch bei Eingruppenabstimmung des Mehrgruppenformat waehlen?
 | 
				
			||||||
 | 
					multigroup = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Bedingungen fuer einen Erfolg der Abstimmung (genau zwei erforderlich).
 | 
				
			||||||
 | 
					# Es muss sich jeweils um gueltigen Perl-Code handeln, Rueckgabewert
 | 
				
			||||||
 | 
					# wird boolesch ausgewertet (true/false). Als Variablen sind $yes
 | 
				
			||||||
 | 
					# und $no zugelassen. Falls oben "proportional = 1" gesetzt wurde,
 | 
				
			||||||
 | 
					# wird nur Bedingung 1 ausgewertet und kann z.B. auf "$yes>$no" gesetzt
 | 
				
			||||||
 | 
					# werden.
 | 
				
			||||||
 | 
					condition1 = $yes>=2*$no
 | 
				
			||||||
 | 
					condition2 = $yes>=60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Ergebnisdatei, in der alle Einzelergebniss zusammengeschrieben werden
 | 
				
			||||||
 | 
					# (wird bei jedem Programmlauf neu erstellt!)
 | 
				
			||||||
 | 
					resultfile = ergebnis.alle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datei fuer Scheinkennungen
 | 
				
			||||||
 | 
					idfile = scheinkennungen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# POP3 benutzen? (falls nicht, wird eine lokale Mailbox eingelesen)
 | 
				
			||||||
 | 
					pop3 = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Mailbox, in der die zu verarbeitenden Mails liegen (falls pop3=0)
 | 
				
			||||||
 | 
					votefile = votes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# POP3-Einstellungen fuer Abruf der eingehenden Wahlscheine:
 | 
				
			||||||
 | 
					# Server, Port, Benutzername, Passwort
 | 
				
			||||||
 | 
					pop3server = 127.0.0.1
 | 
				
			||||||
 | 
					pop3port = 110
 | 
				
			||||||
 | 
					pop3user = test
 | 
				
			||||||
 | 
					pop3pass = test
 | 
				
			||||||
 | 
					# Mail nach dem Abrufen vom Server loeschen?
 | 
				
			||||||
 | 
					pop3delete = 0
 | 
				
			||||||
 | 
					# Dateiname zum Speichern der bereits abgerufenen Mail-IDs (UIDL)
 | 
				
			||||||
 | 
					pop3uidlcache = uidlcache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# POP3-Einstellungen fuer Abruf von Wahlschein-Anforderungen bei Abstimmungen
 | 
				
			||||||
 | 
					# mit personalisierten Wahlscheinen (Punkt 6a der Wahlregeln in de.*)
 | 
				
			||||||
 | 
					# Diese zweite Mailbox ist notwendig, um Wahlschein-Anforderungen und die
 | 
				
			||||||
 | 
					# eigentliche Abstimmung voneinander zu trennen (nicht noetig, wenn
 | 
				
			||||||
 | 
					# personal = 0 gesetzt ist)
 | 
				
			||||||
 | 
					pop3server_req = 127.0.0.1
 | 
				
			||||||
 | 
					pop3port_req = 110
 | 
				
			||||||
 | 
					pop3user_req = test
 | 
				
			||||||
 | 
					pop3pass_req = test
 | 
				
			||||||
 | 
					# Mail nach dem Abrufen vom Server loeschen?
 | 
				
			||||||
 | 
					pop3delete_req = 0
 | 
				
			||||||
 | 
					# Dateiname zum Speichern der bereits abgerufenen Mail-IDs (UIDL)
 | 
				
			||||||
 | 
					pop3uidlcache_req = uidlcache_req
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# POP3-Einstellungen fuer uvbounce.pl (Verarbeitung von Bounces
 | 
				
			||||||
 | 
					# und Generierung einer Liste mit ungueltigen Stimmen). Alle
 | 
				
			||||||
 | 
					# zurueckgekommenen Mails an Waehler sollten in dieser Mailbox landen
 | 
				
			||||||
 | 
					pop3server_bounce = 127.0.0.1
 | 
				
			||||||
 | 
					pop3port_bounce = 110
 | 
				
			||||||
 | 
					pop3user_bounce = test2
 | 
				
			||||||
 | 
					pop3pass_bounce = test2
 | 
				
			||||||
 | 
					# Mail nach dem Abrufen vom Server loeschen?
 | 
				
			||||||
 | 
					pop3delete_bounce = 0
 | 
				
			||||||
 | 
					# Dateiname zum Speichern der bereits abgerufenen Mail-IDs (UIDL)
 | 
				
			||||||
 | 
					pop3uidlcache_bounce = uidlcache_bounce
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					# Alles ab hier braucht i.d.R. nur einmal festgelegt werden.
 | 
				
			||||||
 | 
					# Es ist moeglich, diese Einstellungen in eine globale Konfigurations-
 | 
				
			||||||
 | 
					# datei auszulagern. Das Einbinden erfolgt mit der Zeile
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# include /pfad/zur/globalen_datei
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Falls Einstellungen aus der globalen Konfigurationsdatei hier
 | 
				
			||||||
 | 
					# fuer einzelne Abstimmungen ueberschrieben werden sollen, muessen
 | 
				
			||||||
 | 
					# diese *hinter* dem Include-Befehl stehen!
 | 
				
			||||||
 | 
					# (der letzte Wert ueberschreibt vorhergehende Definitionen)
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SMTP benutzen? (falls nicht, wird der weiter unten einstellbare
 | 
				
			||||||
 | 
					# MTA direkt aufgerufen; unter Windows kann nur SMTP benutzt werden!)
 | 
				
			||||||
 | 
					smtp = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SMTP-Server (falls smtp = 1)
 | 
				
			||||||
 | 
					smtpserver = localhost
 | 
				
			||||||
 | 
					smtpport = 25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SMTP-Authentifizierung benutzen? (RFC 2554)
 | 
				
			||||||
 | 
					# Das entsprechende Perlmodul (Net::SMTP) kann derzeit nur AUTH PLAIN,
 | 
				
			||||||
 | 
					# funktioniert also moeglicherweise nicht mit jedem Server
 | 
				
			||||||
 | 
					#smtpauth = 0
 | 
				
			||||||
 | 
					#smtpuser = 
 | 
				
			||||||
 | 
					#smtppass = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Falls als HELO etwas anderes als der Hostname verwendet werden soll:
 | 
				
			||||||
 | 
					#smtphelo = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Falls ein anderer Fully Qualified Domain Name als der Hostname fuer
 | 
				
			||||||
 | 
					# die Message-ID verwendet werden soll:
 | 
				
			||||||
 | 
					#fqdn =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Verzeichnis fuer fertig verarbeitete Mails und Ergebnisse
 | 
				
			||||||
 | 
					archivedir = fertig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Temporaeres Verzeichnis
 | 
				
			||||||
 | 
					tmpdir = tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Pfad zu den Templates (kommaseparierte Liste mit Verzeichnissen)
 | 
				
			||||||
 | 
					templatedir = templates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Konvertierungsfunktionen für die Templates
 | 
				
			||||||
 | 
					# (kommaseparierte Liste mit Funktions-Modulen)
 | 
				
			||||||
 | 
					formats   = UVformats.pm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dateiname der Steuerungsdatei fuer den Mailversandt
 | 
				
			||||||
 | 
					controlfile = tmp/ack.control
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dateiname des Shellscripts zum Versenden der Bestaetigungsmails (falls smtp=0)
 | 
				
			||||||
 | 
					domailfile = tmp/domail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MTA-Aufruf zum Verschicken der Bestaetigungsmails
 | 
				
			||||||
 | 
					# nuetzlich ist die Sendmail-Option -f zum Setzen des Absenders
 | 
				
			||||||
 | 
					#mailcmd = sendmail -oi -oem -femail@adresse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Weiteres Kommando, welches nach jeder Mail aufgerufen werden soll (falls smtp=0).
 | 
				
			||||||
 | 
					# Sinnvoll ist ein "sleep x", wobei x bei langsamen Systemen hoeher
 | 
				
			||||||
 | 
					# gewaehlt werden sollte, um die Belastung gering zu halten.
 | 
				
			||||||
 | 
					sleepcmd = sleep 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Shellbefehl zum Loeschen des Bildschirms
 | 
				
			||||||
 | 
					# Unix: i.d.R. "clear"
 | 
				
			||||||
 | 
					# Windows: "cls"
 | 
				
			||||||
 | 
					# Falls das Betriebssystem bzw. die Shell keinen solchen Befehl zur Verfuegung
 | 
				
			||||||
 | 
					# stellt, sollte ein Kommando verwendet werden, welches eine Trennlinie
 | 
				
			||||||
 | 
					# oder aehnliches auf dem Bildschirm ausgibt, z.B. mit "echo"
 | 
				
			||||||
 | 
					clearcmd = clear
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Shellbefehl zum seitenweisen Darstellen von Mails auf dem Bildschirm
 | 
				
			||||||
 | 
					# Empfohlene Einstellung: "less", da more Probleme mit der Umleitung von
 | 
				
			||||||
 | 
					# STDERR in eine Datei Probleme hat. Unter Windows ist "less" nicht
 | 
				
			||||||
 | 
					# vorinstallirt, kann man sich aber herunterladen und einfach in das
 | 
				
			||||||
 | 
					# Windows-Verzeichnis kopieren (URL siehe README-Datei)
 | 
				
			||||||
 | 
					pager = less
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datei mit diversen Meldungen und Textfragmenten (Resourcendatei)
 | 
				
			||||||
 | 
					messagefile = messages.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datei mit Wahlregeln
 | 
				
			||||||
 | 
					rulefile = usevote.rul
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datei mit verdaechtigen Mailadressen
 | 
				
			||||||
 | 
					badaddrfile = mailpatterns.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datei fuer Fehlermeldungen beim Programmlauf
 | 
				
			||||||
 | 
					errorfile = errors.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Lockdatei (Verhinderung von mehrfachen Programmstarts)
 | 
				
			||||||
 | 
					lockfile = usevote.lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Einleitungszeile fuer naechste Mail (RegExp)
 | 
				
			||||||
 | 
					mailstart = "^From "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Trennlinien vor und nach dem Wahlschein
 | 
				
			||||||
 | 
					begin_divider = Alles vor dieser Zeile bitte loeschen
 | 
				
			||||||
 | 
					end_divider = Alles nach dieser Zeile bitte loeschen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Text fuer die Namens-Angabe im Wahlschein. Achtung, muss im
 | 
				
			||||||
 | 
					# Wahlschein genauso stehen!
 | 
				
			||||||
 | 
					nametext = Dein Realname, falls nicht im FROM-Header:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Text fuer Namens-Angabe in Bestaetigungsmails
 | 
				
			||||||
 | 
					nametext2 = Waehlername:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Text fuer die Adress-Angabe im Wahlschein
 | 
				
			||||||
 | 
					addresstext = Waehleradresse:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Text für die Angabe der Wahlscheinkennung (siehe Option "personal")
 | 
				
			||||||
 | 
					ballotidtext = Wahlscheinkennung:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Text fuer Datenschutzklausel (siehe Option "bdsg"), erscheint als Abstimmungspunkt
 | 
				
			||||||
 | 
					bdsgtext = Datenschutzklausel - Zustimmung: Ich bin mit der Verarbeitung meiner Daten wie oben beschrieben einverstanden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Datei mit Erklaerungstext fuer BDSG-Klausel
 | 
				
			||||||
 | 
					bdsgfile = bdsgtext.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rechter Rand fuer einige Bildschirmausgaben (Terminalbreite)
 | 
				
			||||||
 | 
					rightmargin = 72
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Regular Expression fuer Erkennung eines gueltigen Realnamens
 | 
				
			||||||
 | 
					name_re = [-a-zA-ZäöüáàâéèêíìîóòôúùûÄÖÜÁÁÂÉÈÊÍÌÎÓÒÔÚÙÛß]{2,} +.*[a-zA-ZäöüáàâéèêíìîóòôúùûÄÖÜÁÁÂÉÈÊÍÌÎÓÒÔÚÙÛß]{2,}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RegExp fuer JA-Stimmen (case-insensitive)
 | 
				
			||||||
 | 
					# Standardmaessig wird J, JA, FUER und DAFUER erkannt
 | 
				
			||||||
 | 
					ja_stimme = (J\s*A|J|(D\s*A\s*)?F\s*U\s*E\s*R)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RegExp fuer NEIN-Stimmen (case-insensitive)
 | 
				
			||||||
 | 
					# Standardmaessig wird N, NEIN, GEGEN und DAGEGEN erkannt
 | 
				
			||||||
 | 
					nein_stimme = (N\s*E\s*I\s*N|N|(D\s*A\s*)?G\s*E\s*G\s*E\s*N)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RegExp fuer ENTHALTUNG (case-insensitive)
 | 
				
			||||||
 | 
					enth_stimme = (E|E\s*N\s*T\s*H\s*A\s*L\s*T\s*U\s*N\s*G)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RegExp fuer ANNULLIERUNG (case-insensitive)
 | 
				
			||||||
 | 
					# Achtung, sollte auch in den Templates im Bestaetigungstext angepasst werden
 | 
				
			||||||
 | 
					ann_stimme = A\s*N\s*N\s*U\s*L\s*L\s*I\s*E\s*R\s*U\s*N\s*G
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Template files (these files are in the template directory defined above)
 | 
				
			||||||
 | 
					tpl_mailheader = "mailheader"            # generally used mail header
 | 
				
			||||||
 | 
					tpl_bouncelist = "bouncelist"            # used by uvbounce.pl
 | 
				
			||||||
 | 
					tpl_result_multi = "result-multi"        # used by uvcount.pl -r -m
 | 
				
			||||||
 | 
					tpl_result_single = "result-single"      # used by uvcount.pl -r -o
 | 
				
			||||||
 | 
					tpl_result_prop = "result-proportional"  # used by uvcount.pl -r (proportional = 1)
 | 
				
			||||||
 | 
					tpl_votes_multi = "votes-multi"          # used by uvcount.pl -v (multiple groups)
 | 
				
			||||||
 | 
					tpl_votes_single = "votes-single"        # used by uvcount.pl -v (single group only)
 | 
				
			||||||
 | 
					tpl_voterlist = "voterlist"              # used by uvcount.pl -l (2nd CfV) 
 | 
				
			||||||
 | 
					tpl_ballot = "ballot"                    # used by uvballot.pl (personal = 0)
 | 
				
			||||||
 | 
					tpl_ballot_request = "ballot-request"    # used by uvballot.pl (personal = 1)
 | 
				
			||||||
 | 
					tpl_ballot_personal = "ballot-personal"  # used by uvcfv.pl    (personal = 1)
 | 
				
			||||||
 | 
					tpl_addr_reg = "address-not-registered"  # used by uvvote.pl   (personal = 1)
 | 
				
			||||||
 | 
					tpl_no_ballotid = "no-ballotid"          # used by uvvote.pl   (personal = 1)
 | 
				
			||||||
 | 
					tpl_wrong_ballotid = "wrong-ballotid"    # used by uvvote.pl   (personal = 1)
 | 
				
			||||||
 | 
					tpl_bdsg_error = "bdsg-error"            # used by uvvote.pl   (bdsg = 1)
 | 
				
			||||||
 | 
					tpl_ack_mail = "ack-mail"                # used by uvvote.pl   (voteack = 1)
 | 
				
			||||||
 | 
					tpl_cancelled = "cancelled"              # used by uvvote.pl
 | 
				
			||||||
 | 
					tpl_invalid_account = "invalid-account"  # used by uvvote.pl
 | 
				
			||||||
 | 
					tpl_invalid_name = "invalid-name"        # used by uvvote.pl
 | 
				
			||||||
 | 
					tpl_multiple_votes = "multiple-votes"    # used by uvvote.pl
 | 
				
			||||||
 | 
					tpl_no_ballot = "no-ballot"              # used by uvvote.pl
 | 
				
			||||||
 | 
					tpl_no_votes = "no-votes"                # used by uvvote.pl
 | 
				
			||||||
 | 
					tpl_rule_violated = "rule-violated"      # used by uvvote.pl   (c.f. usevote.rul)
 | 
				
			||||||
							
								
								
									
										68
									
								
								usevote.rul
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								usevote.rul
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					# UseVote  (c) 1993,94 Ron Dippold, alle Rechte vorbehalten
 | 
				
			||||||
 | 
					#	   uebersetzt von Frederik Ramm
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Mit dieser Datei koennen spezielle Regeln fuer eine gueltige Stimmabgabe
 | 
				
			||||||
 | 
					# bei Mehrgruppenabstimmungen erstellt werden.
 | 
				
			||||||
 | 
					# Beispiel: Eine Gruppe soll aufgeteilt werden, und Du willst erzwingen,
 | 
				
			||||||
 | 
					# dass jemand, der fuer eine der neuen Untergruppen stimmt, auch fuer
 | 
				
			||||||
 | 
					# die .misc-Gruppe stimmen muss. Man kann eine Menge komplexe Sachen hier-
 | 
				
			||||||
 | 
					# mit machen, wenn man Programmierer ist :-)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Das allgemeine Format sieht so aus:
 | 
				
			||||||
 | 
					# (a) alles, was mit # anfaengt, ist ein Kommentar.
 | 
				
			||||||
 | 
					# (b) "echte" Regeln sehen etwa so aus (natuerlich ohne #):
 | 
				
			||||||
 | 
					#   if .jjjjj then J.....
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Eine Regel beginnt immer mit "if", und danach folgen eine Anzahl Symbole;
 | 
				
			||||||
 | 
					# diese Anzahl muss gleich der Anzahl der Gruppen sein, ueber die abgestimmt
 | 
				
			||||||
 | 
					# wird.
 | 
				
			||||||
 | 
					# Oben geht es also um eine Abstimmung ueber sechs Gruppen.
 | 
				
			||||||
 | 
					# Die Symbole zwischen 'if' und 'then' geben an, welche Bedingungen erfuellt
 | 
				
			||||||
 | 
					# sein muessen, damit das System auch die Bedingungen hinter then prueft.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Nach 'then' folgen nochmal so viele Symbole, die angeben, welche Bedin-
 | 
				
			||||||
 | 
					# gungen erfuellt sein muessen, falls die Bedingungen zwischen 'if' und
 | 
				
			||||||
 | 
					# 'then' erfuellt waren. Jeder Wahlschein, auf den das nicht zutrifft, ist
 | 
				
			||||||
 | 
					# ungueltig.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Folgende Symbole sind erlaubt:
 | 
				
			||||||
 | 
					#   J	eine JA-Stimme
 | 
				
			||||||
 | 
					#   N	eine NEIN-Stimme
 | 
				
			||||||
 | 
					#   E	eine Enthaltung
 | 
				
			||||||
 | 
					#   S	eine JA- oder NEIN-Stimme
 | 
				
			||||||
 | 
					#   H   eine Enthaltung oder JA-Stimme
 | 
				
			||||||
 | 
					#   I   eine Enthaltung oder NEIN-Stimme
 | 
				
			||||||
 | 
					#   .	egal (Ja, nein oder Enthaltung)
 | 
				
			||||||
 | 
					#   j	eine oder mehrere der markierten Gruppen hat JA-Stimme
 | 
				
			||||||
 | 
					#   n	 ""   ""    ""     ""     ""       ""    ""  NEIN-Stimme
 | 
				
			||||||
 | 
					#   e	 ""   ""    ""     ""     ""       ""    ""  Enthaltung
 | 
				
			||||||
 | 
					#   s	 ""   ""    ""     ""     ""       ""    ""  Ja- oder Nein-Stimme
 | 
				
			||||||
 | 
					#   h	 ""   ""    ""     ""     ""       ""    ""  Enthaltung oder Ja-Stimme
 | 
				
			||||||
 | 
					#   i	 ""   ""    ""     ""     ""       ""    ""  Enthaltung oder Nein-Stimme
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Alles klar?  Jede Stimme wird mit den Symbolen verglichen, und wenn alle
 | 
				
			||||||
 | 
					# Kriterien passen, ist der Ausdruck wahr. Wenn der erste Ausdruck (if x)
 | 
				
			||||||
 | 
					# wahr ist, muss auch der zeite (then y) wahr sein, sonst ist der Wahlschein
 | 
				
			||||||
 | 
					# ungueltig. Ein Beispiel:
 | 
				
			||||||
 | 
					#   if .jjjjj then J.....
 | 
				
			||||||
 | 
					# Das heisst: Wenn der Waehler fuer *irgendeine* ausser der ersten Gruppe mit
 | 
				
			||||||
 | 
					# JA stimmt, dann *muss* er JA fuer die erste Gruppe stimmen, oder das ganze
 | 
				
			||||||
 | 
					# ist ungueltig.
 | 
				
			||||||
 | 
					# Das koennte z.B. eine Gruppenaufteilung sein, wo fuer die erste (die .misc)-
 | 
				
			||||||
 | 
					# Gruppe gestimmt werden *muss*, wenn fuer eine der anderen gestimmt wird.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Hier noch ein Beispiel:
 | 
				
			||||||
 | 
					#    if S... then .ss.
 | 
				
			||||||
 | 
					#    if .S.. then ..E.
 | 
				
			||||||
 | 
					#    if ..S. then .E..
 | 
				
			||||||
 | 
					# Diese Regeln sagen: Wer fuer die erste Gruppe abstimmt, der muss auch fuer
 | 
				
			||||||
 | 
					# die zweite und dritte Gruppe abstimmen - egal wie. Ausserdem muss er (Re-
 | 
				
			||||||
 | 
					# geln 2 und 3) sich bei 3 enthalten, wenn er bei 2 eine Stimme abgibt und
 | 
				
			||||||
 | 
					# umgekehrt. Die vierte Gruppe wird hier gar nicht betroffen.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Also: es gibt einfache Regeln, aber es sind auch sehr komplizierte Kom-
 | 
				
			||||||
 | 
					# binationen denkar. Das Programm macht alles mit... die Frage ist, ob
 | 
				
			||||||
 | 
					# es die Waehler tun :-)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Fuege Deine Regeln hier an. Mit "uvvote.pl -t" kannst Du sie testen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										116
									
								
								uvballot.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								uvballot.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,116 @@
 | 
				
			||||||
 | 
					#!/usr/bin/perl -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					# UseVoteGer 4.09 Wahlscheingenerierung
 | 
				
			||||||
 | 
					# (c) 2001-2005 Marc Langer <uv@marclanger.de>
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# This script package is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					# modify it under the terms of the GNU Public License as published by the
 | 
				
			||||||
 | 
					# Free Software Foundation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Use this script to create the ballot which can be inserted into the CfV.
 | 
				
			||||||
 | 
					# Not for personal ballots (personal=1 in usevote.cfg), use uvcfv.pl instead.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Many thanks to:
 | 
				
			||||||
 | 
					# - Ron Dippold (Usevote 3.0, 1993/94)
 | 
				
			||||||
 | 
					# - Frederik Ramm (German translation, 1994)
 | 
				
			||||||
 | 
					# - Wolfgang Behrens (UseVoteGer 3.1, based on Frederik's translation, 1998/99)
 | 
				
			||||||
 | 
					# - Cornell Binder for some good advice and code fragments
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is a complete rewrite of UseVoteGer 3.1 in Perl (former versions were
 | 
				
			||||||
 | 
					# written in C). Not all functions of Usevote/UseVoteGer 3.x are implemented!
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Getopt::Long;
 | 
				
			||||||
 | 
					use Text::Wrap qw(wrap $columns);
 | 
				
			||||||
 | 
					use FindBin qw($Bin);
 | 
				
			||||||
 | 
					use lib $Bin;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVtemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my %opt_ctl = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print STDERR "\n$usevote_version Wahlscheingenerierung - (c) 2001-2005 Marc Langer\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# unknown parameters remain in @ARGV (for "help")
 | 
				
			||||||
 | 
					Getopt::Long::Configure(qw(pass_through bundling));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Put known parameters in %opt_ctl
 | 
				
			||||||
 | 
					GetOptions(\%opt_ctl, qw(t|template c|config-file=s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional parameters or invalid options? Show help and exit.
 | 
				
			||||||
 | 
					help() if (@ARGV);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get name auf config file (default: usevote.cfg) and read it
 | 
				
			||||||
 | 
					my $cfgfile   = $opt_ctl{c} || "usevote.cfg";
 | 
				
			||||||
 | 
					UVconfig::read_config($cfgfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set columns for Text::Wrap
 | 
				
			||||||
 | 
					$columns = $config{rightmargin};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($config{personal}) {
 | 
				
			||||||
 | 
					  print_ballot_personal();
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					  print_ballot();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print out a proper ballot                                                  #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub print_ballot {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $template->setKey('votename' => $config{votename});
 | 
				
			||||||
 | 
					  $template->setKey('nametext' => $config{nametext});
 | 
				
			||||||
 | 
					  $template->setKey('bdsg'     => $config{bdsg});
 | 
				
			||||||
 | 
					  $template->setKey('bdsgtext' => $config{bdsgtext});
 | 
				
			||||||
 | 
					  $template->setKey('bdsginfo' => $config{bdsginfo});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (my $n=0; $n<@groups; $n++) {
 | 
				
			||||||
 | 
					     $template->addListItem('groups', pos=>$n+1, group=>$groups[$n]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print $template->processTemplate($config{'tpl_ballot'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Generate a ballot request (if personalized ballots are activated)          #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub print_ballot_personal {
 | 
				
			||||||
 | 
					  my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					  $template->setKey('mailaddress' => $config{mailfrom});
 | 
				
			||||||
 | 
					  print $template->processTemplate($config{'tpl_ballot_request'});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print help text (options and syntax) on -h or --help                       #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub help {
 | 
				
			||||||
 | 
					  print STDERR <<EOF;
 | 
				
			||||||
 | 
					Usage: uvballot.pl [-c config_file]
 | 
				
			||||||
 | 
					       uvballot.pl -h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Generiert den Wahlschein fuer den CfV. Bei personalisierten Wahlscheinen
 | 
				
			||||||
 | 
					(personal = 1 in usevote.cfg) wird nur ein Dummy-Abschnitt mit Hinweisen
 | 
				
			||||||
 | 
					zur Wahlscheinanforderung ausgegeben.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -c config_file   liest die Konfiguration aus config_file
 | 
				
			||||||
 | 
					                   (usevote.cfg falls nicht angegeben)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -h, --help       zeigt diesen Hilfetext an
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										194
									
								
								uvbounce.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								uvbounce.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,194 @@
 | 
				
			||||||
 | 
					#!/usr/bin/perl -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					# UseVoteGer 4.09 Bounce-Verarbeitung
 | 
				
			||||||
 | 
					# (c) 2001-2005 Marc Langer <uv@marclanger.de>
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# This script package is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					# modify it under the terms of the GNU Public License as published by the
 | 
				
			||||||
 | 
					# Free Software Foundation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Use this script to process bounce messages and generate a list of
 | 
				
			||||||
 | 
					# undeliverable voter adresses.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Many thanks to:
 | 
				
			||||||
 | 
					# - Ron Dippold (Usevote 3.0, 1993/94)
 | 
				
			||||||
 | 
					# - Frederik Ramm (German translation, 1994)
 | 
				
			||||||
 | 
					# - Wolfgang Behrens (UseVoteGer 3.1, based on Frederik's translation, 1998/99)
 | 
				
			||||||
 | 
					# - Cornell Binder for some good advice and code fragments
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is a complete rewrite of UseVoteGer 3.1 in Perl (former versions were
 | 
				
			||||||
 | 
					# written in C). Not all functions of Usevote/UseVoteGer 3.x are implemented!
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Getopt::Long;
 | 
				
			||||||
 | 
					use FindBin qw($Bin);
 | 
				
			||||||
 | 
					use lib $Bin;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVreadmail;
 | 
				
			||||||
 | 
					use UVtemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my %opt_ctl = ();
 | 
				
			||||||
 | 
					my %bounces = ();
 | 
				
			||||||
 | 
					my $pop3 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print STDERR "\n$usevote_version Bounce-Verarbeitung - (c) 2001-2005 Marc Langer\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# unknown parameters remain in @ARGV (for "help")
 | 
				
			||||||
 | 
					Getopt::Long::Configure(qw(pass_through bundling));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Put known parameters in %opt_ctl
 | 
				
			||||||
 | 
					GetOptions(\%opt_ctl, qw(h|help f|file config-file=s c=s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get name auf config file (default: usevote.cfg) and read it
 | 
				
			||||||
 | 
					my $cfgfile   = $opt_ctl{'config-file'} || $opt_ctl{c} || "usevote.cfg";
 | 
				
			||||||
 | 
					UVconfig::read_config($cfgfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check POP3 settings in usevote.cfg and combination with -f parameter
 | 
				
			||||||
 | 
					$pop3 = 1 if ($config{pop3} && !$opt_ctl{f});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional parameters or invalid options? Show help and exit. 
 | 
				
			||||||
 | 
					help() if ($opt_ctl{h} || !(@ARGV || $pop3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for lock file
 | 
				
			||||||
 | 
					if (-e $config{lockfile}) {
 | 
				
			||||||
 | 
					  my $lockfile = $config{lockfile};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # don't delete lockfile in END block ;-)
 | 
				
			||||||
 | 
					  $config{lockfile} = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # exit
 | 
				
			||||||
 | 
					  die UVmessage::get("ERR_LOCK", (FILE=>$lockfile)) . "\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# safe exit (delete lockfile)
 | 
				
			||||||
 | 
					$SIG{QUIT} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{INT} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{KILL} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{TERM} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{HUP} = 'sighandler';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# create lock file
 | 
				
			||||||
 | 
					open (LOCKFILE, ">$config{lockfile}");
 | 
				
			||||||
 | 
					close (LOCKFILE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# read and process mails
 | 
				
			||||||
 | 
					# for each mail pass a reference to the sub to be called
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($pop3) {
 | 
				
			||||||
 | 
					  unless (-d $config{archivedir}) {
 | 
				
			||||||
 | 
					    mkdir ($config{archivedir}, 0700)
 | 
				
			||||||
 | 
					      or die UVmessage::get("ERR_MKDIR", (DIR => $config{archivedir})) . "$!\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # mails are saved in file
 | 
				
			||||||
 | 
					  # normally unixtime is sufficient for a unique file name, else append PID
 | 
				
			||||||
 | 
					  my $ext = time;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  opendir (ARCHIVE, $config{archivedir});
 | 
				
			||||||
 | 
					  my @fertigfiles = readdir (ARCHIVE);
 | 
				
			||||||
 | 
					  closedir (ARCHIVE);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  # append PID if file name already exists
 | 
				
			||||||
 | 
					  $ext .= "-$$" if (grep (/$ext/, @fertigfiles));
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  my $file = "$config{archivedir}/bounces-" . $ext;
 | 
				
			||||||
 | 
					  UVreadmail::process($file, \&process_bounce, 2);   # 2 = POP3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					  foreach my $file (@ARGV) {
 | 
				
			||||||
 | 
					    UVreadmail::process($file, \&process_bounce, 3); # 3 = existing file
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach my $address (sort keys %bounces) {
 | 
				
			||||||
 | 
					  my $name = $bounces{$address};
 | 
				
			||||||
 | 
					  my $request = 0;
 | 
				
			||||||
 | 
					  my $text;
 | 
				
			||||||
 | 
					  if ($name eq '***request***') {
 | 
				
			||||||
 | 
					    $name = '';
 | 
				
			||||||
 | 
					    $text = UVmessage::get ("BOUNCE_BALLOT") . "\n";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    $text = UVmessage::get ("BOUNCE_ACKMAIL") . "\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  $name = ' ' unless($name);
 | 
				
			||||||
 | 
					  $template->addListItem('bounces', name=>$name, mail=>$address, bouncetext=>$text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print $template->processTemplate($config{'tpl_bouncelist'});
 | 
				
			||||||
 | 
					exit 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Evaluate a bounce                                                          #
 | 
				
			||||||
 | 
					# This sub is called from UVreadmail::process() for every mail               #
 | 
				
			||||||
 | 
					# Parameters: voter address and name, date header (strings)                  #
 | 
				
			||||||
 | 
					#             complete header and body (references to strings)               #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub process_bounce {
 | 
				
			||||||
 | 
					  # last element of @_ is the body, other stuff not needed here
 | 
				
			||||||
 | 
					  my $body = pop;
 | 
				
			||||||
 | 
					  my ($address, $name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # search body for voter name and address
 | 
				
			||||||
 | 
					  if ($$body =~ /$config{addresstext}\s+(\S+@\S+)/) {
 | 
				
			||||||
 | 
					    $address = $1;
 | 
				
			||||||
 | 
					    if ($$body =~ /$config{nametext2}\s+(.*)$/m) {
 | 
				
			||||||
 | 
					      $name = $1;
 | 
				
			||||||
 | 
					      $bounces{$address} = $name;
 | 
				
			||||||
 | 
					    } elsif ($$body =~ /$config{nametext}/) {
 | 
				
			||||||
 | 
					      # Text from this config option does only appear in ballots,
 | 
				
			||||||
 | 
					      # not in acknowledge mails. So this has to be a bounced ballot request
 | 
				
			||||||
 | 
					      $bounces{$address} = '***request***';
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $bounces{$address} = '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					END {
 | 
				
			||||||
 | 
					  # delete lockfile
 | 
				
			||||||
 | 
					  unlink $config{lockfile} if ($config{lockfile});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub sighandler {
 | 
				
			||||||
 | 
					  my ($sig) = @_;
 | 
				
			||||||
 | 
					  die "\n\nSIG$sig: deleting lockfile and exiting\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print help text (options and syntax) on -h or --help                       #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub help {
 | 
				
			||||||
 | 
					  print <<EOF;
 | 
				
			||||||
 | 
					Usage: uvbounce.pl [-c config_file] [-f] DATEI1 [DATEI2 [...]]
 | 
				
			||||||
 | 
					       uvbounce.pl -h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Liest Bounces aus den uebergebenen Dateien oder aus einer POP3-Mailbox ein
 | 
				
			||||||
 | 
					(Verhalten haengt von usevote.cfg ab) und generiert eine Liste von
 | 
				
			||||||
 | 
					unzustellbaren Adressen, die an den 2. CfV oder das Result angehaengt
 | 
				
			||||||
 | 
					werden kann. Falls POP3 in usevote.cfg eingeschaltet und die Option -f
 | 
				
			||||||
 | 
					(siehe unten) nicht benutzt wurde, werden die uebergebenen Dateinamen
 | 
				
			||||||
 | 
					ignoriert.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -c config_file   liest die Konfiguration aus config_file
 | 
				
			||||||
 | 
					                   (usevote.cfg falls nicht angegeben)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -f, --file       liest die Bounces aus den uebergebenen Dateien, auch
 | 
				
			||||||
 | 
					                   wenn in der Konfigurationsdatei POP3 eingeschaltet ist.
 | 
				
			||||||
 | 
					                   Diese Option wird benoetigt, falls zwar die Stimmzettel
 | 
				
			||||||
 | 
					                   per POP3 eingelesen werden sollen, nicht aber die Bounces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -h, --help       zeigt diesen Hilfetext an
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										282
									
								
								uvcfv.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								uvcfv.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,282 @@
 | 
				
			||||||
 | 
					#!/usr/bin/perl -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					# UseVoteGer 4.09 Personalisierte Wahlscheine
 | 
				
			||||||
 | 
					# (c) 2001-2005 Marc Langer <uv@marclanger.de>
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# This script package is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					# modify it under the terms of the GNU Public License as published by the
 | 
				
			||||||
 | 
					# Free Software Foundation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Use this script to read mails and send back a CfV with unique ballot id
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Many thanks to:
 | 
				
			||||||
 | 
					# - Ron Dippold (Usevote 3.0, 1993/94)
 | 
				
			||||||
 | 
					# - Frederik Ramm (German translation, 1994)
 | 
				
			||||||
 | 
					# - Wolfgang Behrens (UseVoteGer 3.1, based on Frederik's translation, 1998/99)
 | 
				
			||||||
 | 
					# - Cornell Binder for some good advice and code fragments
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is a complete rewrite of UseVoteGer 3.1 in Perl (former versions were
 | 
				
			||||||
 | 
					# written in C). Not all functions of Usevote/UseVoteGer 3.x are implemented!
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Getopt::Long;
 | 
				
			||||||
 | 
					use Digest::MD5 qw(md5_hex);
 | 
				
			||||||
 | 
					use Text::Wrap qw(wrap $columns);
 | 
				
			||||||
 | 
					use FindBin qw($Bin);
 | 
				
			||||||
 | 
					use lib $Bin;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVmenu;
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					use UVreadmail;
 | 
				
			||||||
 | 
					use UVsendmail;
 | 
				
			||||||
 | 
					use UVtemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my %opt_ctl = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print "\n$usevote_version Personalisierte Wahlscheine - (c) 2001-2005 Marc Langer\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# unknown parameters remain in @ARGV (for "help")
 | 
				
			||||||
 | 
					Getopt::Long::Configure(qw(pass_through bundling));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Put known parameters in %opt_ctl
 | 
				
			||||||
 | 
					GetOptions(\%opt_ctl, qw(test t config-file=s c=s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# test mode? (default: no)
 | 
				
			||||||
 | 
					my $test_only = $opt_ctl{test}          || $opt_ctl{t} || 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# # Additional parameters or invalid options? Show help and exit.
 | 
				
			||||||
 | 
					help() if (@ARGV);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get name auf config file (default: usevote.cfg) and read it
 | 
				
			||||||
 | 
					my $cfgfile   = $opt_ctl{'config-file'} || $opt_ctl{c} || "usevote.cfg";
 | 
				
			||||||
 | 
					UVconfig::read_config($cfgfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set columns for Text::Wrap
 | 
				
			||||||
 | 
					$columns = $config{rightmargin};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# read list of suspicious mail addresses from file
 | 
				
			||||||
 | 
					my @bad_addr = UVconfig::read_badaddr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# exit if option "personal=1" in config file not set
 | 
				
			||||||
 | 
					unless ($config{personal}) {
 | 
				
			||||||
 | 
					  die wrap ('', '', UVmessage::get("ERR_NOTPERSONAL", (CFGFILE => $cfgfile))) . "\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# option -t used?
 | 
				
			||||||
 | 
					if ($test_only) {
 | 
				
			||||||
 | 
					  print_ballot();
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for lock file
 | 
				
			||||||
 | 
					if (-e $config{lockfile}) {
 | 
				
			||||||
 | 
					  my $lockfile = $config{lockfile};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # don't delete lockfile in END block ;-)
 | 
				
			||||||
 | 
					  $config{lockfile} = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # exit
 | 
				
			||||||
 | 
					  die UVmessage::get("ERR_LOCK", (FILE=>$lockfile)) . "\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# safe exit (delete lockfile)
 | 
				
			||||||
 | 
					$SIG{QUIT} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{INT} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{KILL} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{TERM} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{HUP} = 'sighandler';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# create lock file
 | 
				
			||||||
 | 
					open (LOCKFILE, ">$config{lockfile}");
 | 
				
			||||||
 | 
					close (LOCKFILE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for tmp directory and domail file
 | 
				
			||||||
 | 
					unless (-d $config{tmpdir}) {
 | 
				
			||||||
 | 
					  mkdir ($config{tmpdir}, 0700)
 | 
				
			||||||
 | 
					    or die UVmessage::get("ERR_MKDIR", (DIR => $config{tmpdir})) . "\n$!\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# generate filename for mail archive
 | 
				
			||||||
 | 
					# normally unixtime is sufficient, if it is not unique append a number
 | 
				
			||||||
 | 
					my $file = my $base = "anforderung-" . time();
 | 
				
			||||||
 | 
					my $count = 0;
 | 
				
			||||||
 | 
					while ($count<1000 && (-e "$config{archivedir}/$file" || -e "$config{tmpdir}/$file")) {
 | 
				
			||||||
 | 
					  $file = "$base-" . ++$count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					die UVmessage::get("ERR_FILE_CREATION") . "\n\n" if ($count == 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unless ($config{pop3}) {
 | 
				
			||||||
 | 
					  rename ($config{requestfile}, "$config{tmpdir}/$file")
 | 
				
			||||||
 | 
					    or die UVmessage::get("ERR_RENAME_MAILFILE") . "$!\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					# wait, so that current mail deliveries can finalize
 | 
				
			||||||
 | 
					sleep 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# initiliaze random number generator
 | 
				
			||||||
 | 
					srand;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# read votes and process them
 | 
				
			||||||
 | 
					# for each mail pass a reference to the sub to be called
 | 
				
			||||||
 | 
					# The third parameter "1" shows that it is called from uvcfv.pl
 | 
				
			||||||
 | 
					$count = UVreadmail::process("$config{tmpdir}/$file", \&process_request, 1);
 | 
				
			||||||
 | 
					print "\n", UVmessage::get("CFV_NUMBER", (COUNT => $count)), "\n\n";
 | 
				
			||||||
 | 
					UVsendmail::send();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print UVmessage::get("INFO_TIDY_UP") . "\n\n";
 | 
				
			||||||
 | 
					rename("$config{tmpdir}/$file", "$config{archivedir}/$file");
 | 
				
			||||||
 | 
					chmod (0400, "$config{archivedir}/$file");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Evaluate a ballot request                                                  #
 | 
				
			||||||
 | 
					# Called from UVreadmail::process() for every mail                           #
 | 
				
			||||||
 | 
					# Parameters: Voter address and name, date header of vote mail (strings),    #
 | 
				
			||||||
 | 
					#             complete header and body (references to Strings)               #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub process_request {
 | 
				
			||||||
 | 
					  my ($voter_addr, $voter_name, $h_date, $entity, $body) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @header = split(/\n/, $entity->stringify_header);
 | 
				
			||||||
 | 
					  my $head = $entity->head;
 | 
				
			||||||
 | 
					  my $msgid = $head->get('Message-ID');
 | 
				
			||||||
 | 
					  chomp($msgid) if ($msgid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # found address?
 | 
				
			||||||
 | 
					  if ($voter_addr) {
 | 
				
			||||||
 | 
					    # check for suspicious addresses
 | 
				
			||||||
 | 
					    foreach my $element (@bad_addr) {
 | 
				
			||||||
 | 
					      if ($voter_addr =~ /^$element/) {
 | 
				
			||||||
 | 
					        my (@votes, @set, $ballot_id); # irrelevant, but necessary for UVmenu::menu()
 | 
				
			||||||
 | 
					        my @errors = ('SuspiciousAccountBallot');
 | 
				
			||||||
 | 
					        my $res = UVmenu::menu(\@votes, \@header, $body, \$voter_addr, \$voter_name, \$ballot_id, \@set, \@errors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # "Ignore": don't deliver a ballot
 | 
				
			||||||
 | 
					        return 0 if ($res eq 'i');
 | 
				
			||||||
 | 
					        if (@errors) {
 | 
				
			||||||
 | 
					          # send error mail if address hasn't been accepted
 | 
				
			||||||
 | 
					          my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					          $template->setKey('head' => $entity->stringify_header);
 | 
				
			||||||
 | 
					          $template->setKey('body' => $$body);
 | 
				
			||||||
 | 
					          my $msg = $template->processTemplate($config{tpl_invalid_account});
 | 
				
			||||||
 | 
					          UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid);
 | 
				
			||||||
 | 
					          return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        last;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else  {
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    # no address found in mail (non-RFC compliant?)
 | 
				
			||||||
 | 
					    my (@votes, @set, $ballot_id); # irrelevant, but necessary for UVmenu::menu()
 | 
				
			||||||
 | 
					    my @errors = ('InvalidAddressBallot');
 | 
				
			||||||
 | 
					    my $res = UVmenu::menu(\@votes, \@header, $body, \$voter_addr, \$voter_name, \$ballot_id, \@set, \@errors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # "ignore" or address not ok: no ballot can be sent
 | 
				
			||||||
 | 
					    return 0 if (@errors || $res eq 'i');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $subject = UVmessage::get("CFV_SUBJECT");
 | 
				
			||||||
 | 
					  my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					  my $ballot_id = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #if ($ballot_id ne $ids{$voter_addr}) {
 | 
				
			||||||
 | 
					  if ($ids{$voter_addr}) {
 | 
				
			||||||
 | 
					    $ballot_id = $ids{$voter_addr};
 | 
				
			||||||
 | 
					    $template->setKey('alreadysent' => 1) if ($ballot_id = $ids{$voter_addr});
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # generate new ballot id from the MD5 sum of header, body and a random value
 | 
				
			||||||
 | 
					    $ballot_id = md5_hex($entity->stringify_header . $body . rand 65535);
 | 
				
			||||||
 | 
					    $ids{$voter_addr} = $ballot_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # write ballot id to file
 | 
				
			||||||
 | 
					    open(IDFILE, ">>$config{idfile}")
 | 
				
			||||||
 | 
					      or die UVmessage::get("CFV_ERRWRITE", (FILE => $config{idfile})) . "\n\n";
 | 
				
			||||||
 | 
					    print IDFILE "$voter_addr $ballot_id\n";
 | 
				
			||||||
 | 
					    close(IDFILE) or die UVmessage::get("CFV_ERRCLOSE") . "\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $template->setKey('ballotid' => $ballot_id);
 | 
				
			||||||
 | 
					  $template->setKey('address'  => $voter_addr);
 | 
				
			||||||
 | 
					  $template->setKey('bdsginfo' => $config{bdsginfo});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (my $n=0; $n<@groups; $n++) {
 | 
				
			||||||
 | 
					     $template->addListItem('groups', pos=>$n+1, group=>$groups[$n]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $msg = $template->processTemplate($config{'tpl_ballot_personal'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # $config{voteaccount} is the Reply-To address:
 | 
				
			||||||
 | 
					  UVsendmail::mail($voter_addr, $subject, $msg, $msgid, $config{voteaccount});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print dummy personalized ballot in STDOUT for checking purposes            #
 | 
				
			||||||
 | 
					# Called if command line argument -t is present                              #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub print_ballot {
 | 
				
			||||||
 | 
					  my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # generate new ballot id
 | 
				
			||||||
 | 
					  my $ballot_id = md5_hex(rand 65535);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $template->setKey('ballotid' => $ballot_id);
 | 
				
			||||||
 | 
					  $template->setKey('address'  => 'dummy@foo.invalid');
 | 
				
			||||||
 | 
					  $template->setKey('bdsginfo' => $config{bdsginfo});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (my $n=0; $n<@groups; $n++) {
 | 
				
			||||||
 | 
					     $template->addListItem('groups', pos=>$n+1, group=>$groups[$n]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $msg = $template->processTemplate($config{'tpl_ballot_personal'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print $msg, "\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Handle Signals and delete lock files when exiting                          #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					END {
 | 
				
			||||||
 | 
					  # delete lockfile
 | 
				
			||||||
 | 
					  unlink $config{lockfile} if ($config{lockfile});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub sighandler {
 | 
				
			||||||
 | 
					  my ($sig) = @_;
 | 
				
			||||||
 | 
					  die "\n\nSIG$sig: deleting lockfile and exiting\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print help text (options and syntax) on -h or --help                       #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub help {
 | 
				
			||||||
 | 
					  print <<EOF;
 | 
				
			||||||
 | 
					Usage: uvcfv.pl [-c config_file] [-t]
 | 
				
			||||||
 | 
					       uvcfv.pl -h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Liest Mailboxen ein und beantwortet alle Mails mit personalisierten CfVs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -c config_file   liest die Konfiguration aus config_file
 | 
				
			||||||
 | 
					                   (usevote.cfg falls nicht angegeben)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -t, --test       gibt einen Dummy-Wahlschein fuer Pruefzwecke aus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -h, --help       zeigt diesen Hilfetext an
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										475
									
								
								uvcount.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								uvcount.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,475 @@
 | 
				
			||||||
 | 
					#!/usr/bin/perl -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					# UseVoteGer 4.09 Stimmauswertung
 | 
				
			||||||
 | 
					# (c) 2001-2005 Marc Langer <uv@marclanger.de>
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# This script package is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					# modify it under the terms of the GNU Public License as published by the
 | 
				
			||||||
 | 
					# Free Software Foundation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Use this script to create voter lists and results.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Many thanks to:
 | 
				
			||||||
 | 
					# - Ron Dippold (Usevote 3.0, 1993/94)
 | 
				
			||||||
 | 
					# - Frederik Ramm (German translation, 1994)
 | 
				
			||||||
 | 
					# - Wolfgang Behrens (UseVoteGer 3.1, based on Frederik's translation, 1998/99)
 | 
				
			||||||
 | 
					# - Cornell Binder for some good advice and code fragments
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is a complete rewrite of UseVoteGer 3.1 in Perl (former versions were
 | 
				
			||||||
 | 
					# written in C). Not all functions of Usevote/UseVoteGer 3.x are implemented!
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Getopt::Long;
 | 
				
			||||||
 | 
					use Digest::MD5 qw(md5_hex);
 | 
				
			||||||
 | 
					use Date::Parse;
 | 
				
			||||||
 | 
					use FindBin qw($Bin);
 | 
				
			||||||
 | 
					use lib $Bin;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVmenu;
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					use UVtemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my %opt_ctl = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print STDERR "\n$usevote_version Stimmauswertung - (c) 2001-2005 Marc Langer\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# unrecognized parameters remain in @ARGV (for "help")
 | 
				
			||||||
 | 
					Getopt::Long::Configure(qw(pass_through bundling));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# recognized parameters are written into %opt_ctl
 | 
				
			||||||
 | 
					GetOptions(\%opt_ctl, qw(l|list v|voters r|result n|nodup m|multigroup o|onegroup c|config-file=s f|result-file=s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!$opt_ctl{r} && ($opt_ctl{m} || $opt_ctl{o})) {
 | 
				
			||||||
 | 
					  print STDERR "Die Optionen -m bzw. -o koennen nur in Verbindung mit -r verwendet werden!\n\n";
 | 
				
			||||||
 | 
					  help(); # show help and exit
 | 
				
			||||||
 | 
					} elsif (@ARGV || !($opt_ctl{l} || $opt_ctl{v} || $opt_ctl{r})) {
 | 
				
			||||||
 | 
					  # additional parameters passed
 | 
				
			||||||
 | 
					  help(); # show help and exit
 | 
				
			||||||
 | 
					} elsif ($opt_ctl{l} && $opt_ctl{v}) {
 | 
				
			||||||
 | 
					  print STDERR "Die Optionen -l und -v duerfen nicht zusammen verwendet werden!\n\n";
 | 
				
			||||||
 | 
					  help(); # show help and exit
 | 
				
			||||||
 | 
					} elsif ($opt_ctl{m} && $opt_ctl{o}) {
 | 
				
			||||||
 | 
					  print STDERR "Die Optionen -m und -o duerfen nicht zusammen verwendet werden!\n\n";
 | 
				
			||||||
 | 
					  help(); # show help and exit
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# get config file name (default: usevote.cfg) and read it
 | 
				
			||||||
 | 
					my $cfgfile   = $opt_ctl{c} || "usevote.cfg";
 | 
				
			||||||
 | 
					UVconfig::read_config($cfgfile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Overwrite result file if started with option -f
 | 
				
			||||||
 | 
					$config{resultfile} = $opt_ctl{f} if ($opt_ctl{f});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					read_resultfile($opt_ctl{n});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Read result file and (optionally) sort out duplicate votes                 #
 | 
				
			||||||
 | 
					# Parameters: 1 if no duplicates should be deleted, else 0                   #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub read_resultfile {
 | 
				
			||||||
 | 
					  my ($nodup) = @_;
 | 
				
			||||||
 | 
					  my $num = 0;
 | 
				
			||||||
 | 
					  my $invalid = '';
 | 
				
			||||||
 | 
					  my $inv_count = 0;
 | 
				
			||||||
 | 
					  my $validcount = 0;
 | 
				
			||||||
 | 
					  my $vote = {};
 | 
				
			||||||
 | 
					  my @votes = ();
 | 
				
			||||||
 | 
					  my @deleted = ();
 | 
				
			||||||
 | 
					  my @votecount = ();
 | 
				
			||||||
 | 
					  my %vnames = ();
 | 
				
			||||||
 | 
					  my %vaddr = ();
 | 
				
			||||||
 | 
					  my %lists = (J => '', N => '', E => '');     # for one-group format
 | 
				
			||||||
 | 
					  my $list = '';                               # for multiple-group format
 | 
				
			||||||
 | 
					  my %varname = (J => 'yes', N => 'no', E => 'abstain');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Initialization of the sum array
 | 
				
			||||||
 | 
					  for (my $group=0; $group<@groups; $group++) {
 | 
				
			||||||
 | 
					    $votecount[$group]->{J} = 0;
 | 
				
			||||||
 | 
					    $votecount[$group]->{N} = 0;
 | 
				
			||||||
 | 
					    $votecount[$group]->{E} = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  open(FILE, "<$config{resultfile}")
 | 
				
			||||||
 | 
					    or die UVmessage::get("COUNT_ERR_OPEN", (FILE=>$config{resultfile})) . "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Read file
 | 
				
			||||||
 | 
					  while(<FILE>) {
 | 
				
			||||||
 | 
					    chomp;
 | 
				
			||||||
 | 
					    $num++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unless (/^(\w): (.*)$/) {
 | 
				
			||||||
 | 
					      print STDERR UVmessage::get("COUNT_ERR_RESULT",
 | 
				
			||||||
 | 
					                                  (FILE=>$config{resultfile}, LINE=>$num)) . "\n";
 | 
				
			||||||
 | 
					      next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $field = $1;
 | 
				
			||||||
 | 
					    my $content = $2;
 | 
				
			||||||
 | 
					    $vote->{$field} = $content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # End of a paragraph reached?
 | 
				
			||||||
 | 
					    if ($field eq 'S') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # The array @votes countains references to the hashes
 | 
				
			||||||
 | 
					      push (@votes, $vote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # For sorting and duplicate detection indexes are build from address and name.
 | 
				
			||||||
 | 
					      # These are hashes containing references to an array of index numbers of
 | 
				
			||||||
 | 
					      # the @votes array.
 | 
				
			||||||
 | 
					      #
 | 
				
			||||||
 | 
					      # Example: $vnames{'marc langer'}->[0] = 2
 | 
				
			||||||
 | 
					      #          $vnames{'marc langer'}->[1] = 10
 | 
				
			||||||
 | 
					      # Meaning: $votes[2] und $votes[10] contain votes of Marc Langer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      push (@{$vnames{lc($vote->{N})}}, $#votes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Conversion in lower case, so that words with an upper case first
 | 
				
			||||||
 | 
					      # letter are not at the top after sorting
 | 
				
			||||||
 | 
					      push (@{$vaddr{lc($vote->{A})}}, $#votes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # reset $vote, begin a new vote
 | 
				
			||||||
 | 
					      $vote = {};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  close(FILE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # delete cancelled votes
 | 
				
			||||||
 | 
					  foreach my $addr (keys %vaddr) {
 | 
				
			||||||
 | 
					    # Run through all votes belonging to a mail address and search for cancellation
 | 
				
			||||||
 | 
					    for (my $n=0; $n<=$#{$vaddr{$addr}}; $n++) {
 | 
				
			||||||
 | 
					      if ($votes[$vaddr{$addr}->[$n]]->{S} =~ /^\*/) {
 | 
				
			||||||
 | 
					        # delete from array
 | 
				
			||||||
 | 
					        push(@deleted, splice(@{$vaddr{$addr}}, 0, $n+1));
 | 
				
			||||||
 | 
					        $n=-1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # sort out duplicates?
 | 
				
			||||||
 | 
					  unless ($nodup) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # search for duplicate addresses
 | 
				
			||||||
 | 
					    foreach my $addr (keys %vaddr) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Run through all votes belonging to a mail address.
 | 
				
			||||||
 | 
					      # If one vote is deleted it has also to be deleted from the array
 | 
				
			||||||
 | 
					      # so that the following addresses move up. In the other case the
 | 
				
			||||||
 | 
					      # counter is incremented as long as further votes are to be compared.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my $n=0;
 | 
				
			||||||
 | 
					      while ($n<$#{$vaddr{$addr}}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        my $ask = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($votes[$vaddr{$addr}->[$n]]->{S} =~ /!/ ||
 | 
				
			||||||
 | 
					            $votes[$vaddr{$addr}->[$n+1]]->{S} =~ /!/)  {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # One of the votes is invalid: Ask votetaker
 | 
				
			||||||
 | 
					          $ask = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # Convert date into unixtime (str2time is located in Date::Parse)
 | 
				
			||||||
 | 
					          my $date1 = str2time($votes[$vaddr{$addr}->[$n]]->{D});
 | 
				
			||||||
 | 
					          my $date2 = str2time($votes[$vaddr{$addr}->[$n+1]]->{D});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # compare dates
 | 
				
			||||||
 | 
					          my $order = $date1 <=> $date2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # first date is earlier
 | 
				
			||||||
 | 
					          if ($order == -1) {
 | 
				
			||||||
 | 
					            push(@deleted, $vaddr{$addr}->[$n]);
 | 
				
			||||||
 | 
					            # delete first element from the array
 | 
				
			||||||
 | 
					            splice(@{$vaddr{$addr}}, $n, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # second date is earlier
 | 
				
			||||||
 | 
					          } elsif ($order == 1) {
 | 
				
			||||||
 | 
					            push(@deleted, $vaddr{$addr}->[$n+1]);
 | 
				
			||||||
 | 
					            # delete second element from the array
 | 
				
			||||||
 | 
					            splice(@{$vaddr{$addr}}, $n+1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # both are equal (ask votetaker)
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            $ask = 1;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Has votetaker to be asked?
 | 
				
			||||||
 | 
					        if ($ask) {
 | 
				
			||||||
 | 
					          my $default = 0;
 | 
				
			||||||
 | 
					          my $res = UVmenu::dup_choice($votes[$vaddr{$addr}->[0]],
 | 
				
			||||||
 | 
					                                       $votes[$vaddr{$addr}->[1]],
 | 
				
			||||||
 | 
					                                       $default);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if ($res == 1) {
 | 
				
			||||||
 | 
					            push(@deleted, $vaddr{$addr}->[0]);
 | 
				
			||||||
 | 
					            # delete first element from the array
 | 
				
			||||||
 | 
					            splice(@{$vaddr{$addr}}, $n, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          } elsif ($res == 2) {
 | 
				
			||||||
 | 
					            push(@deleted, $vaddr{$addr}->[1]);
 | 
				
			||||||
 | 
					            # delete second element from the array
 | 
				
			||||||
 | 
					            splice(@{$vaddr{$addr}}, $n+1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            # don't delete anything: increment counter
 | 
				
			||||||
 | 
					            $n++;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # the same for equal names:
 | 
				
			||||||
 | 
					    foreach my $name (keys %vnames) {
 | 
				
			||||||
 | 
					      my $n = 0;
 | 
				
			||||||
 | 
					      while ($n<$#{$vnames{$name}}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # check if vote was already deleted by prior address sorting
 | 
				
			||||||
 | 
					        if (grep(/^$vnames{$name}->[$n]$/, @deleted)) {
 | 
				
			||||||
 | 
					          # delete first element from the array
 | 
				
			||||||
 | 
					          splice(@{$vnames{$name}}, $n, 1);
 | 
				
			||||||
 | 
					          next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } elsif (grep(/^$vnames{$name}->[$n+1]$/, @deleted)) {
 | 
				
			||||||
 | 
					          # delete second element from the array
 | 
				
			||||||
 | 
					          splice(@{$vnames{$name}}, $n+1, 1);
 | 
				
			||||||
 | 
					          next;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Convert date into unixtime (str2time is located in Date::Parse)
 | 
				
			||||||
 | 
					        my $date1 = str2time($votes[$vnames{$name}->[$n]]->{D});
 | 
				
			||||||
 | 
					        my $date2 = str2time($votes[$vnames{$name}->[$n+1]]->{D});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Set default for menu choice to the earlier vote
 | 
				
			||||||
 | 
					        my $default = ($date2 < $date1) ? 2 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        my $res = UVmenu::dup_choice($votes[$vnames{$name}->[$n]],
 | 
				
			||||||
 | 
					                                     $votes[$vnames{$name}->[$n+1]],
 | 
				
			||||||
 | 
					                                     $default);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # delete first
 | 
				
			||||||
 | 
					        if ($res == 1) {
 | 
				
			||||||
 | 
					          push(@deleted, $vnames{$name}->[$n]);
 | 
				
			||||||
 | 
					          splice(@{$vnames{$name}}, $n, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # delete second
 | 
				
			||||||
 | 
					        } elsif ($res == 2) {
 | 
				
			||||||
 | 
					          push(@deleted, $vnames{$name}->[$n+1]);
 | 
				
			||||||
 | 
					          # delete second element from the array
 | 
				
			||||||
 | 
					          splice(@{$vnames{$name}}, $n+1, 1);
 | 
				
			||||||
 | 
					       
 | 
				
			||||||
 | 
					        # don't delete anything: increment counter
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          $n++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print STDERR UVmessage::get("COUNT_DELETED", (NUM=>scalar @deleted)), "\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Count votes and generate voter list
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  my $list_tpl = UVtemplate->new();
 | 
				
			||||||
 | 
					  $list_tpl->setKey('groupcount' => scalar @groups);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # reversed order as caption string for last column comes first
 | 
				
			||||||
 | 
					  for (my $n=$#groups; $n>=0; $n--) {
 | 
				
			||||||
 | 
					    $list_tpl->addListItem('groups', pos=>@groups-$n, group=>$groups[$n]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					  # loop through all addresses
 | 
				
			||||||
 | 
					  foreach my $addr (sort keys %vaddr) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # loop through all votes for every address
 | 
				
			||||||
 | 
					    for (my $n=0; $n<@{$vaddr{$addr}}; $n++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Ignore vote if already deleted.
 | 
				
			||||||
 | 
					      # If $nodup is not set one single vote should remain
 | 
				
			||||||
 | 
					      unless (grep(/^$vaddr{$addr}->[$n]$/, @deleted)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # extract $vote for simplier code
 | 
				
			||||||
 | 
					        my $vote = $votes[$vaddr{$addr}->[$n]];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # vote is invalid if there is an exclamation mark
 | 
				
			||||||
 | 
					        if ($vote->{S} =~ /!/) {
 | 
				
			||||||
 | 
					          $inv_count++;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          # split vote string into single votes and count
 | 
				
			||||||
 | 
					          my @splitvote = split(//, $vote->{S});
 | 
				
			||||||
 | 
					          if (@groups != @splitvote) {
 | 
				
			||||||
 | 
					            die UVmessage::get("COUNT_ERR_GROUPCOUNT", (ADDR=>$addr, NUM1=>scalar @splitvote,
 | 
				
			||||||
 | 
					                      NUM2=>scalar @groups), RESULTFILE=>$config{resultfile}), "\n\n";
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          for (my $group=0; $group<@splitvote; $group++) {
 | 
				
			||||||
 | 
					            $votecount[$group]->{$splitvote[$group]}++;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          $validcount++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($opt_ctl{l} || $opt_ctl{v}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # vote is invalid if there is an exclamation mark
 | 
				
			||||||
 | 
					          if ($vote->{S} =~ /!/) {
 | 
				
			||||||
 | 
					            $list_tpl->addListItem('invalid', (name=>$vote->{N}, mail=>$vote->{A}, reason=>$vote->{S}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          # in other cases the vote is valid: generate list of votes
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # one-group or multiple-group format?
 | 
				
			||||||
 | 
					            # must use multiple-group data structure for voter list (2. CfV)!
 | 
				
			||||||
 | 
					            if ($#groups || $opt_ctl{l}) {
 | 
				
			||||||
 | 
					              $list_tpl->addListItem('multi', (name=>$vote->{N}, mail=>$vote->{A}, vote=>$vote->{S}));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              my ($votestring) = split(//, $vote->{S});
 | 
				
			||||||
 | 
					              $list_tpl->addListItem($varname{$votestring}, (name=>$vote->{N}, mail=>$vote->{A}));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($opt_ctl{r}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $tplname;
 | 
				
			||||||
 | 
					    my $result_tpl = UVtemplate->new();
 | 
				
			||||||
 | 
					    $result_tpl->setKey('votename' => $config{votename});
 | 
				
			||||||
 | 
					    $result_tpl->setKey('numvalid' => $validcount);
 | 
				
			||||||
 | 
					    $result_tpl->setKey ('numinvalid', $inv_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # proportional vote?
 | 
				
			||||||
 | 
					    if ($config{proportional}) {
 | 
				
			||||||
 | 
					      $tplname = $config{'tpl_result_prop'};
 | 
				
			||||||
 | 
					      for (my $group=0; $group<@votecount; $group++) {
 | 
				
			||||||
 | 
					        # calculate conditions
 | 
				
			||||||
 | 
					        my $yes = $votecount[$group]->{J};
 | 
				
			||||||
 | 
					        my $no = $votecount[$group]->{N};
 | 
				
			||||||
 | 
					        my $cond1 = eval $config{condition1};
 | 
				
			||||||
 | 
					        my $proportion = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # don't evaluate if division by zero
 | 
				
			||||||
 | 
					        unless ($config{prop_formula} =~ m#.+/(.+)# && eval($1)==0) {
 | 
				
			||||||
 | 
					          $proportion = eval $config{prop_formula};
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					        # generate result line
 | 
				
			||||||
 | 
					        $result_tpl->addListItem('count', (yes        => $votecount[$group]->{J},
 | 
				
			||||||
 | 
					                                           no         => $votecount[$group]->{N},
 | 
				
			||||||
 | 
					                                           cond1      => $cond1,
 | 
				
			||||||
 | 
					                                           proportion => $proportion,
 | 
				
			||||||
 | 
					                                           result     => '', # must be set manually
 | 
				
			||||||
 | 
					                                           group      => $groups[$group]));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      # use one-group or multiple-group format?
 | 
				
			||||||
 | 
					      if (@groups == 1 && (!($config{multigroup} || $opt_ctl{m}) || $opt_ctl{o})) {
 | 
				
			||||||
 | 
					        $tplname = $config{'tpl_result_single'};
 | 
				
			||||||
 | 
					        my $yes = $votecount[0]->{J};
 | 
				
			||||||
 | 
					        my $no = $votecount[0]->{N};
 | 
				
			||||||
 | 
					        my $acc1 = eval $config{condition1};
 | 
				
			||||||
 | 
					        my $acc2 = eval $config{condition2};
 | 
				
			||||||
 | 
					        $result_tpl->setKey('yes' => $votecount[0]->{J});
 | 
				
			||||||
 | 
					        $result_tpl->setKey('no' => $votecount[0]->{N});
 | 
				
			||||||
 | 
					        $result_tpl->setKey('numabstain' => $votecount[0]->{E});
 | 
				
			||||||
 | 
					        $result_tpl->setKey('cond1' => $acc1);
 | 
				
			||||||
 | 
					        $result_tpl->setKey('cond2' => $acc2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $tplname = $config{'tpl_result_multi'};
 | 
				
			||||||
 | 
					        $result_tpl->setKey('numabstain' => 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (my $group=0; $group<@votecount; $group++) {
 | 
				
			||||||
 | 
					          # calculate conditions
 | 
				
			||||||
 | 
					          my $yes = $votecount[$group]->{J};
 | 
				
			||||||
 | 
					          my $no = $votecount[$group]->{N};
 | 
				
			||||||
 | 
					          my $cond1 = eval $config{condition1};
 | 
				
			||||||
 | 
					          my $cond2 = eval $config{condition2};
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					          # generate result line
 | 
				
			||||||
 | 
					          $result_tpl->addListItem('count', (yes    => $votecount[$group]->{J},
 | 
				
			||||||
 | 
					                                             no     => $votecount[$group]->{N},
 | 
				
			||||||
 | 
					                                             cond1  => $cond1,
 | 
				
			||||||
 | 
					                                             cond2  => $cond2,
 | 
				
			||||||
 | 
					                                             result => ($cond1 && $cond2),
 | 
				
			||||||
 | 
					                                             group  => $groups[$group]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $result_tpl->setKey ('numabstain', $votecount[0]->{E}) if (@votecount == 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print $result_tpl->processTemplate($tplname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($opt_ctl{v}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # one-group or multiple-group format?
 | 
				
			||||||
 | 
					    if ($#groups) {
 | 
				
			||||||
 | 
					      print $list_tpl->processTemplate($config{'tpl_votes_multi'});
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      print $list_tpl->processTemplate($config{'tpl_votes_single'});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  } elsif ($opt_ctl{l}) {
 | 
				
			||||||
 | 
					    print $list_tpl->processTemplate($config{'tpl_voterlist'});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print help text (options and syntax) on -h or --help                       #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub help {
 | 
				
			||||||
 | 
					  print STDERR <<EOF;
 | 
				
			||||||
 | 
					Usage: uvcount.pl [-c config_file] [-f result_file] [-l | -v] [-r [-m | -o]] [-n]
 | 
				
			||||||
 | 
					       uvcount.pl -h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zaehlt Stimmen und gibt Waehlerlisten aus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -c config_file   liest die Konfiguration aus config_file
 | 
				
			||||||
 | 
					                   (usevote.cfg falls nicht angegeben)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -f result_file   liest die Stimmen aus result_file (ueberschreibt
 | 
				
			||||||
 | 
					                   die "resultfile"-Angabe aus der Konfigurationsdatei)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -l, --list       Gibt eine Liste aller Waehler aus (ohne Stimmen).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -v, --voters     Wie -l, aber mit Angabe der abgegebenen Stimmen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -r, --result     Ausgabe des Endergebnisses (kann mit -l oder -v
 | 
				
			||||||
 | 
					                   kombiniert werden).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -m, --multigroup Benutzt auch bei Eingruppenabstimmungen das
 | 
				
			||||||
 | 
					                   Mehrgruppenformat beim Endergebnis (ueberschreibt
 | 
				
			||||||
 | 
					                   die Einstellung aus usevote.cfg).
 | 
				
			||||||
 | 
					                   Nur in Kombination mit -r verwendbar, schliesst -o aus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -o, --onegroup   Benutzt bei Eingruppenabstimmungen immer das
 | 
				
			||||||
 | 
					                   Eingruppenformat beim Endergebnis (ueberschreibt
 | 
				
			||||||
 | 
					                   die Einstellung aus usevote.cfg).
 | 
				
			||||||
 | 
					                   Nur in Kombination mit -r verwendbar, schliesst -m aus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -n, --nodup      Verzichtet auf das Aussortieren von doppelten
 | 
				
			||||||
 | 
					                   Stimmabgaben. Nicht empfohlen!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -h, --help       zeigt diesen Hilfetext an
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										595
									
								
								uvvote.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										595
									
								
								uvvote.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,595 @@
 | 
				
			||||||
 | 
					#!/usr/bin/perl -w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					# UseVoteGer 4.09 Wahldurchfuehrung
 | 
				
			||||||
 | 
					# (c) 2001-2005 Marc Langer <uv@marclanger.de>
 | 
				
			||||||
 | 
					# 
 | 
				
			||||||
 | 
					# This script package is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					# modify it under the terms of the GNU Public License as published by the
 | 
				
			||||||
 | 
					# Free Software Foundation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The script reads usenet vote ballots from mailbox files. The format
 | 
				
			||||||
 | 
					# can be set by changing the option "mailstart".
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Many thanks to:
 | 
				
			||||||
 | 
					# - Ron Dippold (Usevote 3.0, 1993/94)
 | 
				
			||||||
 | 
					# - Frederik Ramm (German translation, 1994)
 | 
				
			||||||
 | 
					# - Wolfgang Behrens (UseVoteGer 3.1, based on Frederik's translation, 1998/99)
 | 
				
			||||||
 | 
					# - Cornell Binder for some good advice and code fragments
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is a complete rewrite of UseVoteGer 3.1 in Perl (former versions were
 | 
				
			||||||
 | 
					# written in C). Not all functions of Usevote/UseVoteGer 3.x are implemented!
 | 
				
			||||||
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use Getopt::Long;
 | 
				
			||||||
 | 
					use Text::Wrap qw(wrap $columns);
 | 
				
			||||||
 | 
					use FindBin qw($Bin);
 | 
				
			||||||
 | 
					use lib $Bin;
 | 
				
			||||||
 | 
					use UVconfig;
 | 
				
			||||||
 | 
					use UVmenu;
 | 
				
			||||||
 | 
					use UVmessage;
 | 
				
			||||||
 | 
					use UVreadmail;
 | 
				
			||||||
 | 
					use UVsendmail;
 | 
				
			||||||
 | 
					use UVrules;
 | 
				
			||||||
 | 
					use UVtemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $clean = 0;
 | 
				
			||||||
 | 
					my %opt_ctl = ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print "\n$usevote_version Wahldurchfuehrung - (c) 2001-2005 Marc Langer\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# unknown parameters remain in @ARGV (for "help")
 | 
				
			||||||
 | 
					Getopt::Long::Configure(qw(pass_through bundling));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Put known parameters in %opt_ctl
 | 
				
			||||||
 | 
					GetOptions(\%opt_ctl, qw(test t config-file=s c=s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get name auf config file (default: usevote.cfg) and read it
 | 
				
			||||||
 | 
					my $cfgfile   = $opt_ctl{'config-file'} || $opt_ctl{c} || "usevote.cfg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# test mode? (default: no)
 | 
				
			||||||
 | 
					my $test_only = $opt_ctl{test}          || $opt_ctl{t} || 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (@ARGV){
 | 
				
			||||||
 | 
					  # additional parameters passed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($ARGV[0] eq "clean") {
 | 
				
			||||||
 | 
					    $clean = 1;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # print help and exit program
 | 
				
			||||||
 | 
					    help();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UVconfig::read_config($cfgfile, 1);  # read config file, redirect errors to log
 | 
				
			||||||
 | 
					UVrules::read_rulefile();            # read rules from file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# read list of suspicious mail addresses from file
 | 
				
			||||||
 | 
					my @bad_addr = UVconfig::read_badaddr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# option -t used?
 | 
				
			||||||
 | 
					if ($test_only) {
 | 
				
			||||||
 | 
					  UVconfig::test_config();
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for lock file
 | 
				
			||||||
 | 
					if (-e $config{lockfile}) {
 | 
				
			||||||
 | 
					  my $lockfile = $config{lockfile};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # don't delete lockfile in END block ;-)
 | 
				
			||||||
 | 
					  $config{lockfile} = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # exit
 | 
				
			||||||
 | 
					  die UVmessage::get("ERR_LOCK", (FILE=>$lockfile)) . "\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# safe exit (delete lockfile)
 | 
				
			||||||
 | 
					$SIG{QUIT} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{INT} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{KILL} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{TERM} = 'sighandler';
 | 
				
			||||||
 | 
					$SIG{HUP} = 'sighandler';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# create lock file
 | 
				
			||||||
 | 
					open (LOCKFILE, ">$config{lockfile}");
 | 
				
			||||||
 | 
					close (LOCKFILE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set columns for Text::Wrap
 | 
				
			||||||
 | 
					$columns = $config{rightmargin};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for tmp and archive directory
 | 
				
			||||||
 | 
					unless (-d $config{archivedir}) {
 | 
				
			||||||
 | 
					  mkdir ($config{archivedir}, 0700)
 | 
				
			||||||
 | 
					    or die UVmessage::get("ERR_MKDIR", (DIR=>$config{archivedir})) . "$!\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unless (-d $config{tmpdir}) {
 | 
				
			||||||
 | 
					  mkdir ($config{tmpdir}, 0700)
 | 
				
			||||||
 | 
					    or die UVmessage::get("ERR_MKDIR", (DIR=>$config{tmpdir})) . "$!\n\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($clean) {
 | 
				
			||||||
 | 
					  # Program has been startet with "clean" option:
 | 
				
			||||||
 | 
					  # save votes and send out acknowledge mails
 | 
				
			||||||
 | 
					  make_clean();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					  # normal processing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # generate file names for result file
 | 
				
			||||||
 | 
					  # normally unixtime is sufficient, if it is not unique append our PID
 | 
				
			||||||
 | 
					  my $ext = time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  opendir (TMP, $config{tmpdir});
 | 
				
			||||||
 | 
					  my @tmpfiles = readdir (DIR);
 | 
				
			||||||
 | 
					  closedir (TMP);
 | 
				
			||||||
 | 
					  opendir (FERTIG, $config{archivedir});
 | 
				
			||||||
 | 
					  my @fertigfiles = readdir (FERTIG);
 | 
				
			||||||
 | 
					  closedir (FERTIG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # append PID if necessary
 | 
				
			||||||
 | 
					  $ext .= "-$$" if (grep (/$ext/, @tmpfiles) || grep (/$ext/, @fertigfiles));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my $thisresult = "ergebnis-" . $ext;
 | 
				
			||||||
 | 
					  my $thisvotes = "stimmen-" . $ext;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  # POP3 not activated: rename votes file
 | 
				
			||||||
 | 
					  unless ($config{pop3}) {
 | 
				
			||||||
 | 
					    print UVmessage::get("VOTE_RENAMING_MAILBOX"), "\n";
 | 
				
			||||||
 | 
					    rename ($config{votefile}, "$config{tmpdir}/$thisvotes")
 | 
				
			||||||
 | 
					       or die UVmessage::get("ERR_RENAME_MAILFILE") . "$!\n\n";
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    #  wait, so that current mail deliveries can finalize
 | 
				
			||||||
 | 
					    sleep 2;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # open results file
 | 
				
			||||||
 | 
					  open (RESULT, ">>$config{tmpdir}/$thisresult")
 | 
				
			||||||
 | 
					     or die UVmessage::get("VOTE_WRITE_RESULTS", (FILE=>$thisresult)) . "\n\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # read votes and process them
 | 
				
			||||||
 | 
					  # for each mail pass a reference to the sub to be called
 | 
				
			||||||
 | 
					  my $count = UVreadmail::process("$config{tmpdir}/$thisvotes", \&process_vote, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  close (RESULT)
 | 
				
			||||||
 | 
					     or print STDERR UVmessage::get("VOTE_CLOSE_RESULTS", (FILE=>$thisresult)) . "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # no mails: exit here
 | 
				
			||||||
 | 
					  unless ($count) {
 | 
				
			||||||
 | 
					    print UVmessage::get("VOTE_NO_VOTES") . "\n\n";
 | 
				
			||||||
 | 
					    exit 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($config{onestep}) {
 | 
				
			||||||
 | 
					    # everything should be done in one step
 | 
				
			||||||
 | 
					    print "\n" . UVmessage::get("VOTE_NUM_VOTES", (COUNT=>$count)) . "\n";
 | 
				
			||||||
 | 
					    make_clean();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print "\n", UVmessage::get("VOTE_NOT_SAVED", (COUNT=>$count)), "\n",
 | 
				
			||||||
 | 
					          wrap('', '', UVmessage::get("VOTE_FIRSTRUN")), "\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					END {
 | 
				
			||||||
 | 
					  close (STDERR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # delete lockfile
 | 
				
			||||||
 | 
					  unlink $config{lockfile} if ($config{lockfile});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (-s $config{errorfile}) {
 | 
				
			||||||
 | 
					    # errors ocurred
 | 
				
			||||||
 | 
					    print '*' x $config{rightmargin}, "\n",
 | 
				
			||||||
 | 
					          UVmessage::get("VOTE_ERRORS",(FILE => $config{errorfile})), "\n",
 | 
				
			||||||
 | 
					          '*' x $config{rightmargin}, "\n\n";
 | 
				
			||||||
 | 
					    open (ERRFILE, "<$config{errorfile}");
 | 
				
			||||||
 | 
					    print <ERRFILE>;
 | 
				
			||||||
 | 
					    close (ERRFILE);
 | 
				
			||||||
 | 
					    print "\n";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    unlink ($config{errorfile});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub sighandler {
 | 
				
			||||||
 | 
					  my ($sig) = @_;
 | 
				
			||||||
 | 
					  die "\n\nSIG$sig: deleting lockfile and exiting\n\n";
 | 
				
			||||||
 | 
					} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Evaluation of a vote mail                                                  #
 | 
				
			||||||
 | 
					# Called from UVreadmail::process() for each mail.                           #
 | 
				
			||||||
 | 
					# Parameters: voter address and name, date header of the vote mail (strings) #
 | 
				
			||||||
 | 
					#             complete header (reference to array), body (ref. to strings)   #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub process_vote {
 | 
				
			||||||
 | 
					  my ($voter_addr, $voter_name, $h_date, $entity, $body) = @_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @header = split(/\n/, $entity->stringify_header);
 | 
				
			||||||
 | 
					  my $head = $entity->head;
 | 
				
			||||||
 | 
					  my $msgid = $head->get('Message-ID');
 | 
				
			||||||
 | 
					  chomp($msgid) if ($msgid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @votes = ();              # the votes
 | 
				
			||||||
 | 
					  my @set;                     # interactively changed fields
 | 
				
			||||||
 | 
					  my @errors = ();             # recognized errors (show menu for manual action)
 | 
				
			||||||
 | 
					  my $onevote = 0;             # 0=no votes, 1=everything OK, 2=vote cancelled
 | 
				
			||||||
 | 
					  my $voteerror = "";          # error message in case of invalid vote
 | 
				
			||||||
 | 
					  my $ballot_id = "";          # ballot id (German: Wahlscheinkennung)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # found address?
 | 
				
			||||||
 | 
					  if ($voter_addr) {
 | 
				
			||||||
 | 
					    # search for suspicious addresses
 | 
				
			||||||
 | 
					    foreach my $element (@bad_addr) {
 | 
				
			||||||
 | 
					      if ($voter_addr =~ /^$element/) {
 | 
				
			||||||
 | 
					        push (@errors, 'SuspiciousAccount');
 | 
				
			||||||
 | 
					        last;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # found no address in mail (perhaps violates RFC?)
 | 
				
			||||||
 | 
					    push (@errors, 'InvalidAddress');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # personalized ballots?
 | 
				
			||||||
 | 
					  if ($config{personal}) {
 | 
				
			||||||
 | 
					    if ($$body =~ /$config{ballotidtext}\s+([a-z0-9]+)/) {
 | 
				
			||||||
 | 
					      $ballot_id = $1;
 | 
				
			||||||
 | 
					      # Address registered? ($ids is set in UVconfig.pm)
 | 
				
			||||||
 | 
					      if ($ids{$voter_addr}) {
 | 
				
			||||||
 | 
					        push (@errors, 'WrongBallotID') if ($ids{$voter_addr} ne $ballot_id);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        push (@errors, 'AddressNotRegistered');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      push (@errors, 'NoBallotID');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					  # evaluate vote strings
 | 
				
			||||||
 | 
					  for (my $n=0; $n<@groups; $n++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # counter starts at 1 in ballot
 | 
				
			||||||
 | 
					    my $votenum = $n+1;
 | 
				
			||||||
 | 
					    my $vote = "";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # a line looks like this: #1 [ VOTE ] Group
 | 
				
			||||||
 | 
					    # matching only on number and vote, because of line breaks likely
 | 
				
			||||||
 | 
					    # inserted by mail programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # duplicate vote?
 | 
				
			||||||
 | 
					    if ($$body =~ /#$votenum\W*?\[\s*?(\w+)\s*?\].+?#$votenum\W*?\[\s*?(\w+)\s*?\]/s) {
 | 
				
			||||||
 | 
					      push (@errors, "DuplicateVote") if ($1 ne $2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # this matches on a single appearance:
 | 
				
			||||||
 | 
					    if ($$body =~ /#$votenum\W*?\[(.+)\]/) {
 | 
				
			||||||
 | 
					      # one or more vote strings were found
 | 
				
			||||||
 | 
					      $onevote = 1;
 | 
				
			||||||
 | 
					      my $votestring = $1;
 | 
				
			||||||
 | 
					      if ($votestring =~ /^\W*$config{ja_stimme}\W*$/i) {
 | 
				
			||||||
 | 
					        $vote = "J";
 | 
				
			||||||
 | 
					      } elsif ($votestring =~ /^\W*$config{nein_stimme}\W*$/i) {
 | 
				
			||||||
 | 
					        $vote = "N";
 | 
				
			||||||
 | 
					      } elsif ($votestring =~ /^\W*$config{enth_stimme}\W*$/i) {
 | 
				
			||||||
 | 
					        $vote = "E";
 | 
				
			||||||
 | 
					      } elsif ($votestring =~ /^\s*$/) {
 | 
				
			||||||
 | 
					        # nothing has been entered between the [ ]
 | 
				
			||||||
 | 
					        $vote = "E";
 | 
				
			||||||
 | 
					      } elsif ($votestring =~ /^\W*$config{ann_stimme}\W*$/i) {
 | 
				
			||||||
 | 
					        $vote = "A";
 | 
				
			||||||
 | 
					        $onevote = 2;        # Cancelled vote: set $onevote to 2
 | 
				
			||||||
 | 
					      } elsif (!$votes[$n]) {
 | 
				
			||||||
 | 
					        # vote not recognized
 | 
				
			||||||
 | 
					        $vote = "E";
 | 
				
			||||||
 | 
					        push (@errors, 'UnrecognizedVote #' . $votenum . "#$votestring");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      push (@votes, $vote);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      # vote not found
 | 
				
			||||||
 | 
					      push (@votes, 'E');
 | 
				
			||||||
 | 
					      push (@errors, 'UnrecognizedVote #' . $votenum . '#(keine Stimmabgabe fuer "'
 | 
				
			||||||
 | 
					           . $groups[$n] . '" gefunden)');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($onevote == 0) {
 | 
				
			||||||
 | 
					    push (@errors, "NoVote") unless ($onevote);
 | 
				
			||||||
 | 
					  } elsif ($onevote == 1) {
 | 
				
			||||||
 | 
					    # check rules
 | 
				
			||||||
 | 
					    my $rule = UVrules::rule_check(\@votes);
 | 
				
			||||||
 | 
					    push (@errors, "ViolatedRule #$rule") if ($rule);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # cancelled vote: replace all votes with an A
 | 
				
			||||||
 | 
					    @votes = split(//, 'A' x scalar @votes);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Evaluate Data Protection Law clause (not on cancelled votes)
 | 
				
			||||||
 | 
					  if ($config{bdsg} && $onevote<2) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Text in ballot complete and clause accepted?
 | 
				
			||||||
 | 
					    # Should read like this: #a [ STIMME ] Text
 | 
				
			||||||
 | 
					    # (Text is configurable in usevote.cfg)
 | 
				
			||||||
 | 
					    unless ($$body =~ /$bdsg_regexp/s &&
 | 
				
			||||||
 | 
					            $$body =~ /#a\W*?\[\W*?$config{ja_stimme}\W*?\]\W*?$bdsg2_regexp/is) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      push (@errors, 'InvalidBDSG');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Name in body?
 | 
				
			||||||
 | 
					  if ($$body =~ /($config{nametext}|$config{nametext2})( |\t)*(\S.+?)$/m) {
 | 
				
			||||||
 | 
					    $voter_name = $3;
 | 
				
			||||||
 | 
					    $voter_name =~ s/^\s+//; # strip leading spaces
 | 
				
			||||||
 | 
					    $voter_name =~ s/\s+$//; # strip trailing spaces
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ($voter_name) {
 | 
				
			||||||
 | 
					    # Name invalid?
 | 
				
			||||||
 | 
					    push (@errors, 'InvalidName') unless ($voter_name =~ /$config{name_re}/);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    # no name found:
 | 
				
			||||||
 | 
					    push (@errors, 'NoName') unless ($voter_name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Errors encountered?
 | 
				
			||||||
 | 
					  if (@errors) {
 | 
				
			||||||
 | 
					    my $res = UVmenu::menu(\@votes, \@header, $body, \$voter_addr, \$voter_name,
 | 
				
			||||||
 | 
					                           \$ballot_id, \@set, \@errors);
 | 
				
			||||||
 | 
					    return 0 if ($res eq 'i');      # "Ignore": Ignore vote, don't save
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my $tpl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Check Ballot ID stuff
 | 
				
			||||||
 | 
					    if ($config{personal}) {
 | 
				
			||||||
 | 
					      if ($ballot_id) {
 | 
				
			||||||
 | 
					        if ($ids{$voter_addr}) {
 | 
				
			||||||
 | 
					          if ($ids{$voter_addr} ne $ballot_id) {
 | 
				
			||||||
 | 
					            $voteerror = UVmessage::get("VOTE_INVALID_BALLOTID");
 | 
				
			||||||
 | 
					            $tpl = $config{tpl_wrong_ballotid};
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          $voteerror = UVmessage::get("VOTE_UNREGISTERED_ADDRESS");
 | 
				
			||||||
 | 
					          $tpl = $config{tpl_addr_reg};
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $voteerror = UVmessage::get("VOTE_MISSING_BALLOTID");
 | 
				
			||||||
 | 
					        $tpl = $config{tpl_no_ballotid};
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      # generate error mail (if error occurred)
 | 
				
			||||||
 | 
					      if ($tpl) {
 | 
				
			||||||
 | 
					        my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					        $template->setKey('head' => $entity->stringify_header);
 | 
				
			||||||
 | 
					        $template->setKey('body' => $$body);
 | 
				
			||||||
 | 
					        my $msg = $template->processTemplate($tpl);
 | 
				
			||||||
 | 
					        UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  # Check rules and send error mail unless rule violation was ignored in the use menu
 | 
				
			||||||
 | 
					  # or another error was detected
 | 
				
			||||||
 | 
					  if (grep(/ViolatedRule/, @errors) && !$voteerror && (my $rule = UVrules::rule_check(\@votes))) {
 | 
				
			||||||
 | 
					    $voteerror = UVmessage::get("VOTE_VIOLATED_RULE", (RULE=>$rule));
 | 
				
			||||||
 | 
					    my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					    $template->setKey('body'  => $$body);
 | 
				
			||||||
 | 
					    $template->setKey('rules' => UVrules::rule_print($rule-1));
 | 
				
			||||||
 | 
					    my $msg = $template->processTemplate($config{tpl_rule_violated});
 | 
				
			||||||
 | 
					    UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!$voteerror && @errors) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # turn errors array into hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    my %error;
 | 
				
			||||||
 | 
					    foreach my $error (@errors) {
 | 
				
			||||||
 | 
					      $error{$error} = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Check uncorrected errors
 | 
				
			||||||
 | 
					    if ($error{InvalidBDSG}) {
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{tpl_bdsg_error});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    } elsif ($error{NoVote}) {
 | 
				
			||||||
 | 
					      $voteerror = UVmessage::get("VOTE_NO_VOTES");
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      $template->setKey('body'  => $$body);
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{tpl_no_votes});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					    } elsif ($error{SuspiciousAccount}) {
 | 
				
			||||||
 | 
					      $voteerror = UVmessage::get("VOTE_INVALID_ACCOUNT");
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      $template->setKey('head' => $entity->stringify_header);
 | 
				
			||||||
 | 
					      $template->setKey('body'  => $$body);
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{tpl_invalid_account});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					    } elsif ($error{InvalidAddress}) {
 | 
				
			||||||
 | 
					      $voteerror = UVmessage::get("VOTE_INVALID_ADDRESS");
 | 
				
			||||||
 | 
					    } elsif ($error{InvalidName}) {
 | 
				
			||||||
 | 
					      $voteerror = UVmessage::get("VOTE_INVALID_REALNAME");
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      $template->setKey('head' => $entity->stringify_header);
 | 
				
			||||||
 | 
					      $template->setKey('body'  => $$body);
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{tpl_invalid_name});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					    } elsif ($error{DuplicateVote}) {
 | 
				
			||||||
 | 
					      $voteerror = UVmessage::get("VOTE_DUPLICATES");
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      $template->setKey('head' => $entity->stringify_header);
 | 
				
			||||||
 | 
					      $template->setKey('body'  => $$body);
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{tpl_multiple_votes});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # check voter name
 | 
				
			||||||
 | 
					  unless ($voter_name || $voteerror) {
 | 
				
			||||||
 | 
					    $voteerror = UVmessage::get("VOTE_MISSING_NAME");
 | 
				
			||||||
 | 
					    my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					    $template->setKey('head' => $entity->stringify_header);
 | 
				
			||||||
 | 
					    $template->setKey('body'  => $$body);
 | 
				
			||||||
 | 
					    my $msg = $template->processTemplate($config{tpl_invalid_name});
 | 
				
			||||||
 | 
					    UVsendmail::mail($voter_addr, "Fehler", $msg, $msgid) if ($config{voteack});
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # set mark for cancelled vote
 | 
				
			||||||
 | 
					  $onevote = 2 if ($votes[0] eq 'A');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # create comment line for result file
 | 
				
			||||||
 | 
					  my $comment;
 | 
				
			||||||
 | 
					  if ($config{personal}) {
 | 
				
			||||||
 | 
					    # Personalized Ballots: insert ballot id
 | 
				
			||||||
 | 
					    $comment = "($ballot_id)";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    $comment = "()";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (@set) {
 | 
				
			||||||
 | 
					    $comment .= ' '.UVmessage::get("VOTE_FILE_COMMENT", (FIELDS => join(', ', @set)));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # write result file
 | 
				
			||||||
 | 
					  print RESULT "A: $voter_addr\n";
 | 
				
			||||||
 | 
					  print RESULT "N: $voter_name\n";
 | 
				
			||||||
 | 
					  print RESULT "D: $h_date\n";
 | 
				
			||||||
 | 
					  print RESULT "K: $comment\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # invalid vote?
 | 
				
			||||||
 | 
					  if ($voteerror) {
 | 
				
			||||||
 | 
					    print RESULT "S: ! $voteerror\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # cancelled vote?
 | 
				
			||||||
 | 
					  } elsif ($onevote == 2) {
 | 
				
			||||||
 | 
					    print RESULT "S: * Annulliert\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($config{voteack}) {
 | 
				
			||||||
 | 
					      # send cancellation acknowledge
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{tpl_cancelled});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Bestaetigung", $msg, $msgid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    print RESULT "S: ", join ("", @votes), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # send acknowledge mail?
 | 
				
			||||||
 | 
					    if ($config{voteack}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my $template = UVtemplate->new();
 | 
				
			||||||
 | 
					      $template->setKey(ballotid        => $ballot_id);
 | 
				
			||||||
 | 
					      $template->setKey(address         => $voter_addr);
 | 
				
			||||||
 | 
					      $template->setKey(name            => $voter_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (my $n=0; $n<@groups; $n++) {
 | 
				
			||||||
 | 
					        my $vote = $votes[$n];
 | 
				
			||||||
 | 
					        $vote =~ s/^J$/JA/;
 | 
				
			||||||
 | 
					        $vote =~ s/^N$/NEIN/;
 | 
				
			||||||
 | 
					        $vote =~ s/^E$/ENTHALTUNG/;
 | 
				
			||||||
 | 
					        $template->addListItem('groups', pos=>$n+1, vote=>$vote, group=>$groups[$n]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					      my $msg = $template->processTemplate($config{'tpl_ack_mail'});
 | 
				
			||||||
 | 
					      UVsendmail::mail($voter_addr, "Bestaetigung", $msg, $msgid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Send out acknowledge mails and tidy up (we're called as "uvvote.pl clean") #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub make_clean {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # send mails
 | 
				
			||||||
 | 
					  UVsendmail::send();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print UVmessage::get("INFO_TIDY_UP"), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # search unprocessed files
 | 
				
			||||||
 | 
					  opendir (DIR, $config{tmpdir});
 | 
				
			||||||
 | 
					  my @files = readdir DIR;
 | 
				
			||||||
 | 
					  closedir (DIR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  my @resultfiles = grep (/^ergebnis-/, @files);
 | 
				
			||||||
 | 
					  my @votefiles = grep (/^stimmen-/, @files);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  unless (@resultfiles) {
 | 
				
			||||||
 | 
					    print wrap('', '', UVmessage::get("VOTE_NO_NEW_RESULTS")), "\n\n";
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }   
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $thisresult (@resultfiles) {
 | 
				
			||||||
 | 
					    chmod (0400, "$config{tmpdir}/$thisresult");
 | 
				
			||||||
 | 
					    rename "$config{tmpdir}/$thisresult", "$config{archivedir}/$thisresult"
 | 
				
			||||||
 | 
					      or die UVmessage::get("VOTE_MOVE_RESULTFILE", (FILE=>$thisresult)) . "$!\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  foreach my $thisvotes (@votefiles) {
 | 
				
			||||||
 | 
					    chmod (0400, "$config{tmpdir}/$thisvotes");
 | 
				
			||||||
 | 
					    rename "$config{tmpdir}/$thisvotes", "$config{archivedir}/$thisvotes"
 | 
				
			||||||
 | 
					      or die UVmessage::get("VOTE_MOVE_VOTEFILE", (FILE=>$thisvotes)) . "$!\n\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print UVmessage::get("VOTE_CREATING_RESULTS", (FILENAME=>$config{resultfile})), "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # search all result files
 | 
				
			||||||
 | 
					  opendir (DIR, "$config{archivedir}/");
 | 
				
			||||||
 | 
					  @files = grep (/^ergebnis-/, readdir (DIR));
 | 
				
			||||||
 | 
					  closedir (DIR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Create complete result from all single result files.
 | 
				
			||||||
 | 
					  # The resulting file (ergebnis.alle) is overwritten as there could have been
 | 
				
			||||||
 | 
					  # made changes in the single result files
 | 
				
			||||||
 | 
					  open(RESULT, ">$config{resultfile}");
 | 
				
			||||||
 | 
					  foreach my $file (sort @files) {
 | 
				
			||||||
 | 
					    open(THISRESULT, "<$config{archivedir}/$file");
 | 
				
			||||||
 | 
					    print RESULT join('', <THISRESULT>);
 | 
				
			||||||
 | 
					    close(THISRESULT);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  close(RESULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					# Print help text (options and syntax) on -h or --help                       #
 | 
				
			||||||
 | 
					##############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub help {
 | 
				
			||||||
 | 
					  print <<EOF;
 | 
				
			||||||
 | 
					Usage: uvvote.pl [-c config_file] [-t]
 | 
				
			||||||
 | 
					       uvvote.pl [-c config_file] clean
 | 
				
			||||||
 | 
					       uvvote.pl -h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Liest Mailboxen aus einer Datei oder per POP3 ein wertet die Mails
 | 
				
			||||||
 | 
					als Stimmzettel aus. Erst beim Aufruf mit der Option "clean" werden
 | 
				
			||||||
 | 
					die Ergebnisse endgueltig gespeichert und die Bestaetigungsmails
 | 
				
			||||||
 | 
					verschickt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -c config_file   liest die Konfiguration aus config_file
 | 
				
			||||||
 | 
					                   (usevote.cfg falls nicht angegeben)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -t, --test       fuehrt einen Test der Konfiguration durch und
 | 
				
			||||||
 | 
					                   gibt das ermittelte Ergebnis aus.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  -h, --help       zeigt diesen Hilfetext an
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exit 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue