Merge branch 'master' of vc.linet-services.de:public/lx-office-erp
authorThomas Heck <theck@linet-services.de>
Fri, 24 Aug 2012 13:50:23 +0000 (15:50 +0200)
committerThomas Heck <theck@linet-services.de>
Fri, 24 Aug 2012 13:50:23 +0000 (15:50 +0200)
13 files changed:
SL/Dispatcher.pm
SL/InstallationCheck.pm
SL/Mailer.pm
SL/Mailer/SMTP.pm [new file with mode: 0644]
SL/Mailer/Sendmail.pm [new file with mode: 0644]
SL/Template/ShellCommand.pm
bin/mozilla/admin.pl
config/lx_office.conf.default
doc/release_management.txt
locale/de/all
templates/webpages/admin/check_auth_database.html
templates/webpages/admin/check_auth_tables.html
templates/webpages/menu/header.html

index 9083b8d..43bf668 100644 (file)
@@ -2,9 +2,18 @@ package SL::Dispatcher;
 
 use strict;
 
+# Force scripts/locales.pl to parse these templates:
+#   parse_html_template('login_screen/auth_db_unreachable')
+#   parse_html_template('login_screen/user_login')
+#   parse_html_template('generic/error')
+
 BEGIN {
-  unshift @INC, "modules/override"; # Use our own versions of various modules (e.g. YAML).
-  push    @INC, "modules/fallback"; # Only use our own versions of modules if there's no system version.
+  use SL::System::Process;
+  my $exe_dir = SL::System::Process::exe_dir;
+
+  unshift @INC, "${exe_dir}/modules/override"; # Use our own versions of various modules (e.g. YAML).
+  push    @INC, "${exe_dir}/modules/fallback"; # Only use our own versions of modules if there's no system version.
+  unshift @INC, $exe_dir;
 }
 
 use CGI qw( -no_xhtml);
@@ -249,6 +258,7 @@ sub handle_request {
     if ($EVAL_ERROR ne END_OF_REQUEST) {
       print STDERR $EVAL_ERROR;
       $::form->{label_error} = $::request->{cgi}->pre($EVAL_ERROR);
+      chdir SL::System::Process::exe_dir;
       eval { show_error('generic/error') };
     }
   };
index 27581ad..6ae1494 100644 (file)
@@ -39,6 +39,9 @@ BEGIN {
   { name => "Digest::SHA",                         url => "http://search.cpan.org/~mshelor/",   debian => 'libdigest-sha-perl' },
   { name => "IO::Socket::SSL",                     url => "http://search.cpan.org/~sullr/",     debian => 'libio-socket-ssl-perl' },
   { name => "Net::LDAP",                           url => "http://search.cpan.org/~gbarr/",     debian => 'libnet-ldap-perl' },
+  # Net::LDAP is core since 5.7.3
+  { name => "Net::SMTP::SSL",  version => '1.01',  url => "http://search.cpan.org/~cwest/",     debian => 'libnet-smtp-ssl-perl' },
+  { name => "Net::SMTP::TLS",  version => '0.12',  url => "http://search.cpan.org/~awestholm/", debian => 'libnet-smtp-tls-perl' },
 );
 
 @developer_modules = (
index edd0eec..b04af08 100644 (file)
@@ -52,6 +52,25 @@ sub new {
   bless $self, $type;
 }
 
+sub _create_driver {
+  my ($self) = @_;
+
+  my %params = (
+    mailer   => $self,
+    form     => $::form,
+    myconfig => \%::myconfig,
+  );
+
+  my $cfg = $::lx_office_conf{mail_delivery};
+  if (($cfg->{method} || 'smtp') ne 'smtp') {
+    require SL::Mailer::Sendmail;
+    return SL::Mailer::Sendmail->new(%params);
+  } else {
+    require SL::Mailer::SMTP;
+    return SL::Mailer::SMTP->new(%params);
+  }
+}
+
 sub mime_quote_text {
   $main::lxdebug->enter_sub();
 
@@ -99,7 +118,7 @@ sub send {
 
   my ($self) = @_;
 
-  local (*IN, *OUT);
+  local (*IN);
 
   $num_sent++;
   my $boundary    = time() . "-$$-${num_sent}";
@@ -111,16 +130,10 @@ sub send {
   my $form        =  $main::form;
   my $myconfig    =  \%main::myconfig;
 
-  my $email       =  $self->recode($myconfig->{email});
-  $email          =~ s/[^\w\.\-\+=@]//ig;
-
-  my %temp_form   = ( %{ $form }, 'myconfig_email' => $email );
-  my $template    = SL::Template::create(type => 'PlainText', form => \%temp_form);
-  my $sendmail    = $template->parse_block($::lx_office_conf{applications}->{sendmail});
-
-  if (!open(OUT, "|$sendmail")) {
+  my $driver = eval { $self->_create_driver };
+  if (!$driver) {
     $main::lxdebug->leave_sub();
-    return "$sendmail : $!";
+    return "send email : $@";
   }
 
   $self->{charset}     ||= Common::DEFAULT_CHARSET;
@@ -137,13 +150,17 @@ sub send {
 
   $self->{from} = $self->recode($self->{from});
 
+  my %addresses;
   my $headers = '';
   foreach my $item (qw(from to cc bcc)) {
+    $addresses{$item} = [];
     next unless ($self->{$item});
+
     my (@addr_objects) = Email::Address->parse($self->{$item});
     next unless (scalar @addr_objects);
 
     foreach my $addr_obj (@addr_objects) {
+      push @{ $addresses{$item} }, $addr_obj->address;
       my $phrase = $addr_obj->phrase();
       if ($phrase) {
         $phrase =~ s/^\"//;
@@ -151,28 +168,28 @@ sub send {
         $addr_obj->phrase($self->mime_quote_text($phrase));
       }
 
-      $headers .= sprintf("%s: %s\n", ucfirst($item), $addr_obj->format());
+      $headers .= sprintf("%s: %s\n", ucfirst($item), $addr_obj->format()) unless $driver->keep_from_header($item);
     }
   }
 
   $headers .= sprintf("Subject: %s\n", $self->mime_quote_text($self->recode($self->{subject}), 60));
 
-  print OUT qq|${headers}Message-ID: <$msgid>
+  $driver->start_mail(from => $self->{from}, to => [ map { @{ $addresses{$_} } } qw(to cc bcc) ]);
+
+  $driver->print(qq|${headers}Message-ID: <$msgid>
 X-Mailer: Lx-Office $self->{version}
 MIME-Version: 1.0
-|;
+|);
 
   if ($self->{attachments}) {
-    print OUT qq|Content-Type: multipart/mixed; boundary="$boundary"
-
-|;
+    $driver->print(qq|Content-Type: multipart/mixed; boundary="$boundary"\n\n|);
     if ($self->{message}) {
-      print OUT qq|--${boundary}
+      $driver->print(qq|--${boundary}
 Content-Type: $self->{contenttype}; charset="$self->{charset}"
 
 | . $self->recode($self->{message}) . qq|
 
-|;
+|);
     }
 
     foreach my $attachment (@{ $self->{attachments} }) {
@@ -195,7 +212,6 @@ Content-Type: $self->{contenttype}; charset="$self->{charset}"
 
       open(IN, $attachment);
       if ($?) {
-        close(OUT);
         $main::lxdebug->leave_sub();
         return "$attachment : $!";
       }
@@ -207,31 +223,31 @@ Content-Type: $self->{contenttype}; charset="$self->{charset}"
         $attachment_charset = qq|; charset="$self->{charset}" |;
       }
 
-      print OUT qq|--${boundary}
+      $driver->print(qq|--${boundary}
 Content-Type: ${content_type}; name="$filename"$attachment_charset
 Content-Transfer-Encoding: BASE64
-Content-Disposition: attachment; filename="$filename"\n\n|;
+Content-Disposition: attachment; filename="$filename"\n\n|);
 
       my $msg = "";
       while (<IN>) {
         ;
         $msg .= $_;
       }
-      print OUT &encode_base64($msg);
+      $driver->print(encode_base64($msg));
 
       close(IN);
 
     }
-    print OUT qq|--${boundary}--\n|;
+    $driver->print(qq|--${boundary}--\n|);
 
   } else {
-    print OUT qq|Content-Type: $self->{contenttype}; charset="$self->{charset}"
+    $driver->print(qq|Content-Type: $self->{contenttype}; charset="$self->{charset}"
 
 | . $self->recode($self->{message}) . qq|
-|;
+|);
   }
 
-  close(OUT);
+  $driver->send;
 
   $main::lxdebug->leave_sub();
 
@@ -274,4 +290,3 @@ sub recode {
 }
 
 1;
-
diff --git a/SL/Mailer/SMTP.pm b/SL/Mailer/SMTP.pm
new file mode 100644 (file)
index 0000000..831bd72
--- /dev/null
@@ -0,0 +1,87 @@
+package SL::Mailer::SMTP;
+
+use strict;
+
+use parent qw(Rose::Object);
+
+use Rose::Object::MakeMethods::Generic
+(
+  scalar => [ qw(myconfig mailer form) ]
+);
+
+sub init {
+  my ($self) = @_;
+
+  Rose::Object::init(@_);
+
+  my $cfg           = $::lx_office_conf{mail_delivery} || {};
+  $self->{security} = lc($cfg->{security} || 'none');
+
+  if ($self->{security} eq 'tls') {
+    require Net::SMTP::TLS;
+    my %params;
+    if ($cfg->{login}) {
+      $params{User}     = $cfg->{user};
+      $params{Password} = $cfg->{password};
+    }
+    $self->{smtp} = Net::SMTP::TLS->new($cfg->{host} || 'localhost', Port => $cfg->{port} || 25, %params);
+
+  } else {
+    my $module       = $self->{security} eq 'ssl' ? 'Net::SMTP::SSL' : 'Net::SMTP';
+    my $default_port = $self->{security} eq 'ssl' ? 465              : 25;
+    eval "require $module" or die $@;
+
+    $self->{smtp} = $module->new($cfg->{host} || 'localhost', Port => $cfg->{port} || $default_port);
+    $self->{smtp}->auth($cfg->{user}, $cfg->{password}) if $cfg->{login};
+  }
+
+  die unless $self->{smtp};
+}
+
+sub start_mail {
+  my ($self, %params) = @_;
+
+  $self->{smtp}->mail($params{from});
+  $self->{smtp}->recipient(@{ $params{to} });
+  $self->{smtp}->data;
+}
+
+sub print {
+  my $self = shift;
+
+  # SMTP requires at most 1000 characters per line. Each line must be
+  # terminated with <CRLF>, meaning \r\n in Perl.
+
+  # First, normalize the string by removing all \r in order to fix
+  # possible wrong combinations like \n\r.
+  my $str = join '', @_;
+  $str    =~ s/\r//g;
+
+  # Now remove the very last newline so that we don't create a
+  # superfluous empty line at the very end.
+  $str =~ s/\n$//;
+
+  # Split the string on newlines keeping trailing empty parts. This is
+  # requires so that input like "Content-Disposition: ..... \n\n" is
+  # treated correctly. That's also why we had to remove the very last
+  # \n in the prior step.
+  my @lines = split /\n/, $str, -1;
+
+  # Send each line terminating it with \r\n.
+  $self->{smtp}->datasend("$_\r\n") for @lines;
+}
+
+sub send {
+  my ($self) = @_;
+
+  $self->{smtp}->dataend;
+  $self->{smtp}->quit;
+  delete $self->{smtp};
+}
+
+sub keep_from_header {
+  my ($self, $item) = @_;
+  return lc($item) eq 'bcc';
+}
+
+1;
diff --git a/SL/Mailer/Sendmail.pm b/SL/Mailer/Sendmail.pm
new file mode 100644 (file)
index 0000000..6b24ecd
--- /dev/null
@@ -0,0 +1,50 @@
+package SL::Mailer::Sendmail;
+
+use strict;
+
+use IO::File;
+use SL::Template;
+
+use parent qw(Rose::Object);
+
+use Rose::Object::MakeMethods::Generic
+(
+  scalar => [ qw(myconfig mailer form) ]
+);
+
+sub init {
+  my ($self) = @_;
+
+  Rose::Object::init(@_);
+
+  my $email         =  $self->mailer->recode($self->myconfig->{email});
+  $email            =~ s/[^\w\.\-\+=@]//ig;
+
+  my %temp_form     = ( %{ $self->form }, myconfig_email => $email );
+  my $template      = SL::Template::create(type => 'ShellCommand', form => \%temp_form);
+  my $sendmail      = $::lx_office_conf{applications}->{sendmail} || $::lx_office_conf{mail_delivery}->{sendmail} || "sendmail -t";
+  $sendmail         = $template->parse_block($sendmail);
+
+  $self->{sendmail} = IO::File->new("|$sendmail") || die "sendmail($sendmail): $!";
+}
+
+sub start_mail {
+}
+
+sub print {
+  my $self = shift;
+
+  $self->{sendmail}->print(@_);
+}
+
+sub send {
+  my ($self) = @_;
+  $self->{sendmail}->close;
+  delete $self->{sendmail};
+}
+
+sub keep_from_header {
+  0;
+}
+
+1;
index 0824129..9ea4b8f 100644 (file)
@@ -35,7 +35,7 @@ sub substitute_vars {
 sub format_string {
   my ($self, $variable) = @_;
 
-  return shell_quote_best_effort($variable);
+  return shell_quote($variable);
 }
 
 sub get_mime_type {
index 4409505..7581e9b 100755 (executable)
@@ -146,6 +146,8 @@ sub check_auth_db_and_tables {
 
   map { $params{"db_${_}"} = $main::auth->{DB_config}->{$_} } keys %{ $auth->{DB_config} };
 
+  $params{admin_password} = $::lx_office_conf{authentication}->{admin_password};
+
   if (!$main::auth->check_database()) {
     $form->{title} = $locale->text('Authentification database creation');
     $form->header();
index 7b95f4c..bb66bce 100644 (file)
@@ -102,9 +102,29 @@ templates = templates
 # Path to the old memberfile (ignored on new installations)
 memberfile = users/members
 
-[applications]
-# Location of sendmail
+[mail_delivery]
+# Delivery method can be 'sendmail' or 'smtp' (the default). For
+# 'method = sendmail' the parameter 'mail_delivery.sendmail' is used
+# as the executable to call. If 'applications.sendmail' still exists
+# (backwards compatibility) then 'applications.sendmail' will be used
+# instead of 'mail_delivery.sendmail'.
+method = smtp
+# Location of sendmail for 'method = sendmail'
 sendmail = /usr/sbin/sendmail -t<%if myconfig_email%> -f <%myconfig_email%><%end%>
+# Settings for 'method = smtp'.
+host = localhost
+port = 25
+# Security can be 'tls', 'ssl' or 'none'. Unset equals 'none'. This
+# determines whether or not encryption is used and which kind. For
+# 'tls' the module 'Net::SMTP::TLS' is required; for 'ssl'
+# 'Net::SMTP::TLS' is required and 'none' only uses 'Net::SMTP'.
+security = tls
+# Authentication is only used if 'login' is set. You should only use
+# that with 'tls' or 'ssl' encryption.
+login =
+password =
+
+[applications]
 # Location of OpenOffice.org writer
 openofficeorg_writer = oowriter
 # Location of the X virtual frame buffer used for OpenOffice
index 791d082..36d4c16 100644 (file)
@@ -20,6 +20,30 @@ als freundliche Checkliste zum ausdrucken und erweitern.
 1. KONSISTENZ DES PROGRAMMS
 ===========================
 
+* Testlauf t/test.sh
+
+  - Im Moment sind 4 Fehler optimal (die sind noch nicht angegangen):
+    o  bin/mozilla/ar.pl contains at least 190 html tags.
+    o  bin/mozilla/ic.pl contains at least 130 html tags.
+    o  bin/mozilla/ap.pl contains at least 183 html tags.
+    o  bin/mozilla/admin.pl DOES NOT use proper system or exec calls
+  - Einige Tests setzen eine korrekt aufgesetzte Datenbank für tests voraus.
+    TODO: diese Tests korrekt skippen wenn keine DB gefunden wurde.
+    TODO: Dokumeniteren wie der Releasemanager sich so eine DB baut, die
+          sollten vor einem Release zumindest durchlaufen.
+    TODO: Evtl eine Klasse von Releasetests einführen)
+
+* Testinstallation aus dem git mit neuer auth Datenbank.
+
+  - Änderungen die die auth Systeme betreffen zerreissen gerne mal die initiale
+    Installation.
+
+* Testupgrade auf einer Vorversion.
+
+  - Dito nur mit Upgradescripten. Fehlerhafte Abhängigkeiten können dazu
+    führen, dass Upgradescripte nicht in der richtigen Reihenfolge ausgeführt
+    werden, was bei inkrementellem Testen nicht auffällt.
+
 * Freeze auf der Mailingliste ansagen.
 
   - Featurefreeze für beta
@@ -153,16 +177,7 @@ als freundliche Checkliste zum ausdrucken und erweitern.
 
   t/test.sh
 
-  - Im Moment sind 4 Fehler optimal (die sind noch nicht angegangen):
-    o  bin/mozilla/ar.pl contains at least 190 html tags.
-    o  bin/mozilla/ic.pl contains at least 130 html tags.
-    o  bin/mozilla/ap.pl contains at least 183 html tags.
-    o  bin/mozilla/admin.pl DOES NOT use proper system or exec calls
-  - Einige Tests setzen eine korrekt aufgesetzte Datenbank für tests voraus.
-    TODO: diese Tests korrekt skippen wenn keine DB gefunden wurde.
-    TODO: Dokumeniteren wie der Releasemanager sich so eine DB baut, die
-          sollten vor einem Release zumindest durchlaufen.
-    TODO: Evtl eine Klasse von Releasetests einführen)
+  Siehe oben für mögliche Ergebnisse.
 
 * Alle Änderungen einchecken.
 
index dc275c0..28db532 100644 (file)
@@ -942,6 +942,7 @@ $self->{texts} = {
   'If you select a base unit then you also have to enter a factor.' => 'Wenn Sie eine Basiseinheit auswählen, dann müssen Sie auch einen Faktor eingeben.',
   'If you want to change any of these parameters then press the &quot;Back&quot; button, edit the file &quot;config/lx_office.conf&quot; and login into the admin module again.' => 'Wenn Sie einen der Parameter &auml;ndern wollen, so dr&uuml;cken Sie auf den &quot;Zur&uuml;ck&quot;-Button, bearbeiten Sie die Datei &quot;config/lx_office.conf&quot;, und melden Sie sich erneut im Administrationsbereich an.',
   'If you want to delete such a dataset you have to edit the user(s) that are using the dataset in question and have them use another dataset.' => 'Wenn Sie eine solche Datenbank l&ouml;schen wollen, so m&uuml;ssen Sie zuerst die Benutzer bearbeiten, die die fragliche Datenbank benutzen, und sie so &auml;ndern, dass sie eine andere Datenbank benutzen.',
+  'If you want to set up the authentication database yourself then log in to the administration panel. kivitendo will then create the database and tables for you.' => 'Wenn Sie die Authentifizierungs-Datenbank selber einrichten wollen, so melden Sie sich im Administrationsbereich an. kivitendo wird dann die Datenbank und die erforderlichen Tabellen für Sie anlegen.',
   'Image'                       => 'Grafik',
   'Import'                      => 'Import',
   'Import CSV'                  => 'CSV-Import',
@@ -968,7 +969,7 @@ $self->{texts} = {
   'Incoming Payments'           => 'Zahlungseingänge',
   'Incoming invoice number'     => 'Eingangsrechnungsnummer',
   'Incorrect Password!'         => 'Ungültiges Passwort!',
-  'Incorrect password!'         => '',
+  'Incorrect password!'         => 'Ungültiges Passwort!',
   'Incorrect username or password!' => 'Ungültiger Benutzername oder falsches Passwort!',
   'Increase'                    => 'Erhöhen',
   'Individual Items'            => 'Einzelteile',
@@ -1183,7 +1184,6 @@ $self->{texts} = {
   'Netto Terms'                 => 'Zahlungsziel netto',
   'New Buchungsgruppe #1'       => 'Neue Buchungsgruppe #1',
   'New Templates'               => 'Erzeuge Vorlagen, Name',
-  'New Win/Tab'                 => 'Neues Fenster',
   'New assembly'                => 'Neues Erzeugnis',
   'New bank account'            => 'Neues Bankkonto',
   'New contact'                 => 'Neuer Ansprechpartner',
@@ -1195,6 +1195,7 @@ $self->{texts} = {
   'New shipto'                  => 'Neue Lieferadresse',
   'New unit'                    => 'Neue Einheit',
   'New vendor'                  => 'Neuer Lieferant',
+  'New window/tab'              => 'Neues Fenster/Tab',
   'Next Dunning Level'          => 'Nächste Mahnstufe',
   'No'                          => 'Nein',
   'No %s was found matching the search parameters.' => 'Es wurde kein %s gefunden, auf den die Suchparameter zutreffen.',
@@ -1280,7 +1281,7 @@ $self->{texts} = {
   'Oops. No valid action found to dispatch. Please report this case to the Lx-Office team.' => 'Ups. Es wurde keine gültige Funktion zum Aufrufen gefunden. Bitte berichten Sie diesen Fall den Lx-Office-Entwicklern.',
   'Open'                        => 'Offen',
   'Open Amount'                 => 'Offener Betrag',
-  'Open a further kivitendo Window or Tab' => '',
+  'Open a further kivitendo window or tab' => 'Weiteres kivitendo-Fenster/-Tab öffnen',
   'Open amount'                 => 'offener Betrag',
   'Open in new window'          => 'In neuem Fenster &ouml;ffnen.',
   'Open this Website'           => 'Homepage in neuem Fenster &ouml;ffnen',
@@ -1437,8 +1438,8 @@ $self->{texts} = {
   'Printer Management'          => 'Druckeradministration',
   'Printers are created for a user database. Please select a user. The associated database will be edited.' => 'Drucker werden für eine Benutzerdatenbank erzeugt. Bitte wählen Sie einen Benutzer aus. Die Drucker werden in der verknüpften Datenbank angelegt.',
   'Printing ... '               => 'Es wird gedruckt.',
-  'Prior to version v2.4.0 the user could enter arbitrary strings as units for parts, services and in invoices, sales quotations etc.' => '',
-  'Prior to version v2.4.0 the user had to chose the accounts for each part and service.' => '',
+  'Prior to version v2.4.0 the user could enter arbitrary strings as units for parts, services and in invoices, sales quotations etc.' => 'Vor Version v2.4.0 konnten die Benutzer sowohl in den Artikelstammdaten als auch in Belegen wie Rechnungen, Angeboten etc. beliebige Dinge als Einheit eintragen.',
+  'Prior to version v2.4.0 the user had to chose the accounts for each part and service.' => 'Vor Version v2.4.0 mussten Benutzer für Artikel und Dienstleistungen jedes einzelne Buchungskonto auswählen.',
   'Private E-mail'              => 'Private eMail',
   'Private Phone'               => 'Privates Tel.',
   'Problem'                     => 'Problem',
@@ -1800,6 +1801,7 @@ $self->{texts} = {
   'The application "#1" was not found on the system.' => 'Die Anwendung "#1" wurde auf dem System nicht gefunden.',
   'The assembly has been created.' => 'Das Erzeugnis wurde hergestellt.',
   'The assistant could not find anything wrong with #1. Maybe the problem has been solved in the meantime.' => 'Der Korrekturassistent konnte kein Problem bei #1 feststellen. Eventuell wurde das Problem in der Zwischenzeit bereits behoben.',
+  'The authentication database is not reachable at the moment. Either it hasn\'t been set up yet or the database server might be down. Please contact your administrator.' => 'Die Authentifizierungs-Datenbank kann momentan nicht erreicht werden. Entweder wurde sie noch nicht eingerichtet, oder der Datenbankserver ist momentan nicht verfügbar. Bitte wenden Sie sich an Ihren Administrator.',
   'The available options depend on the varibale type:' => 'Die verf&uuml;gbaren Optionen h&auml;ngen vom Variablentypen ab:',
   'The backup you upload here has to be a file created with &quot;pg_dump -o -Ft&quot;.' => 'Die von Ihnen hochzuladende Sicherungsdatei muss mit dem Programm und den Parametern &quot;pg_dump -o -Ft&quot; erstellt worden sein.',
   'The bank information must not be empty.' => 'Die Bankinformationen müssen vollständig ausgefüllt werden.',
@@ -1821,7 +1823,7 @@ $self->{texts} = {
   'The custom variable has been deleted.' => 'Die benutzerdefinierte Variable wurde gel&ouml;scht.',
   'The custom variable has been saved.' => 'Die benutzerdefinierte Variable wurde gespeichert.',
   'The database #1 has been successfully deleted.' => 'Die Datenbank #1 wurde erfolgreich gelöscht.',
-  'The database for user management and authentication does not exist. You can create let kivitendo create it with the following parameters:' => '',
+  'The database for user management and authentication does not exist. You can create let kivitendo create it with the following parameters:' => 'Die Datenbank für die Benutzeranmeldung existiert nicht. Sie können Sie von kivitendo automatisch mit den folgenden Parametern anlegen lassen:',
   'The database update/creation did not succeed. The file #1 contained the following error:' => 'Die Datenbankaktualisierung/erstellung schlug fehl. Die Datei #1 enthielt den folgenden Fehler:',
   'The database upgrade for the introduction of Buchungsgruppen is now complete.' => 'Das Datenbankupgrade f&uuml;r die Einf&uuml;hrung von Buchungsgruppen ist jetzt beendet.',
   'The database upgrade for the introduction of units is now complete.' => 'Das Datenbankupgrade zwecks Einf&uuml;hrung von Einheiten ist nun beendet.',
@@ -1849,7 +1851,7 @@ $self->{texts} = {
   'The end date is the last day for which invoices will possibly be created.' => 'Das Enddatum ist das letztmögliche Datum, an dem eine Rechnung erzeugt wird.',
   'The factor is missing in row %d.' => 'Der Faktor fehlt in Zeile %d.',
   'The factor is missing.'      => 'Der Faktor fehlt.',
-  'The first reason is that kivitendo contained a bug which resulted in the wrong taxkeys being recorded for transactions in which two entries are posted for the same chart with different taxkeys.' => '',
+  'The first reason is that kivitendo contained a bug which resulted in the wrong taxkeys being recorded for transactions in which two entries are posted for the same chart with different taxkeys.' => 'Der erste Grund war ein Fehler in kivitendo, der dazu führte, dass bei einer Transaktion, bei der zwei Buchungen mit unterschiedlichen Steuerschlüsseln auf dasselbe Konto durchgeführt wurden, die falschen Steuerschlüssel gespeichert wurden.',
   'The follow-up date is missing.' => 'Das Wiedervorlagedatum fehlt.',
   'The following Buchungsgruppen have already been created:' => 'Die folgenden Buchungsgruppen wurden bereits angelegt:',
   'The following Datasets need to be updated' => 'Folgende Datenbanken müssen aktualisiert werden',
@@ -1900,7 +1902,7 @@ $self->{texts} = {
   'The project has been saved.' => 'Das Projekt wurde gespeichert.',
   'The restoration process has started. Here\'s the output of the &quot;pg_restore&quot; command:' => 'Der Wiederherstellungsprozess wurde gestartet. Hier ist die Ausgabe des &quot;pg_restore&quot;-Programmes:',
   'The restoration process is complete. Please review &quot;pg_restore&quot;\'s output to find out if the restoration was successful.' => 'Die Wiederherstellung ist abgeschlossen. Bitte sehen Sie sich die Ausgabe von &quot;pg_restore&quot; an, um festzustellen, ob die Wiederherstellung erfolgreich war.',
-  'The second reason is that kivitendo allowed the user to enter the tax amount manually regardless of the taxkey used.' => '',
+  'The second reason is that kivitendo allowed the user to enter the tax amount manually regardless of the taxkey used.' => 'Der zweite Grund war, dass kivitendo zuließ, dass die Benutzer beliebige, von den tatsächlichen Steuerschlüsseln unabhängige Steuerbeträge eintrugen.',
   'The second way is to use Perl\'s CPAN module and let it download and install the module for you.' => 'Die zweite Variante besteht darin, Perls CPAN-Modul zu benutzen und es das Modul f&uuml;r Sie installieren zu lassen.',
   'The selected  PostgreSQL installation uses UTF-8 as its encoding. Therefore you have to configure Lx-Office to use UTF-8 as well.' => 'Die ausgewählte PostgreSQL-Installation benutzt UTF-8 als Zeichensatz. Deshalb müssen Sie Lx-Office so konfigurieren, dass es ebenfalls UTF-8 als Zeichensatz benutzt.',
   'The selected bank account does not exist anymore.' => 'Das ausgewählte Bankkonto existiert nicht mehr.',
@@ -1941,7 +1943,7 @@ $self->{texts} = {
   'There are still entries in the database for which no unit has been assigned.' => 'Es gibt noch Eintr&auml;ge in der Datenbank, f&uuml;r die keine Einheit zugeordnet ist.',
   'There are still transfers not matching the qty of the delivery order. Stock operations can not be changed later. Do you really want to proceed?' => 'Einige der Lagerbewegungen sind nicht vollständig und Lagerbewegungen können nachträglich nicht mehr verändert werden. Wollen Sie wirklich fortfahren?',
   'There are usually three ways to install Perl modules.' => 'Es gibt normalerweise drei Arten, ein Perlmodul zu installieren.',
-  'There is at least one sales or purchase invoice for which kivitendo recorded an inventory transaction with taxkeys even though no tax was recorded.' => '',
+  'There is at least one sales or purchase invoice for which kivitendo recorded an inventory transaction with taxkeys even though no tax was recorded.' => 'Es gibt mindestens eine Verkaufs- oder Einkaufsrechnung, für die kivitendo eine Warenbestandsbuchung ohne dazugehörige Steuerbuchung durchgeführt hat.',
   'There is at least one transaction for which the user has chosen a logically wrong taxkey.' => 'Es gibt mindestens eine Buchung, bei der ein logisch nicht passender Steuerschlüssel ausgewählt wurde.',
   'There is not enough available of \'#1\' at warehouse \'#2\', bin \'#3\', #4, #5, for the transfer of #6.' => 'Von \'#1\' ist in Lager \'#2\', Lagerplatz \'#3\', #4, #5, nicht gen&uuml;gend eingelagert, um insgesamt #6 auszulagern.',
   'There is not enough available of \'#1\' at warehouse \'#2\', bin \'#3\', #4, for the transfer of #5.' => 'Von \'#1\' ist in Lager \'#2\', Lagerplatz \'#3\', #4 nicht gen&uuml;gend eingelagert, um insgesamt #5 auszulagern.',
@@ -1949,9 +1951,9 @@ $self->{texts} = {
   'There is nothing to do in this step.' => 'In diesem Schritt gibt es nichts mehr zu tun.',
   'Therefore the definition of "kg" with the base unit "g" and a factor of 1000 is valid while defining "g" with a base unit of "kg" and a factor of "0.001" is not.' => 'So ist die Definition von "kg" mit der Basiseinheit "g" und dem Faktor 1000 zulässig, die Definition von "g" mit der Basiseinheit "kg" und dem Faktor "0,001" hingegen nicht.',
   'Therefore there\'s no need to create the same article more than once if it is sold or bought in/from another tax zone.' => 'Deswegen muss man den gleichen Artikel nicht mehr mehrmals anlegen, wenn er in verschiedenen Steuerzonen gehandelt werden soll.',
-  'These units can be based on other units so that kivitendo can convert prices when the user switches from one unit to another.' => '',
+  'These units can be based on other units so that kivitendo can convert prices when the user switches from one unit to another.' => 'Einheiten können auf anderen Einheiten basieren, sodass kivitendo Preise automatisch umrechnen kann, wenn die Benutzer zwischen solchen Einheiten umschalten.',
   'These wrong entries cannot be fixed automatically.' => 'Diese Einträge können nicht automatisch bereinigt werden.',
-  'This corresponds to kivitendo\'s behavior prior to version 2.4.4.' => '',
+  'This corresponds to kivitendo\'s behavior prior to version 2.4.4.' => 'Dies entspricht kivitendos Verhalten vor Version 2.4.4.',
   'This could have happened for two reasons:' => 'Dies kann aus zwei Gründen geschehen sein:',
   'This customer number is already in use.' => 'Diese Kundennummer wird bereits verwendet.',
   'This group will be called &quot;Full Access&quot;.' => 'Diese Gruppe wird &quot;Vollzugriff&quot; genannt.',
@@ -2091,7 +2093,7 @@ $self->{texts} = {
   'Vendors'                     => 'Lieferanten',
   'Verrechnungseinheit'         => 'Verrechnungseinheit',
   'Version'                     => 'Version',
-  'Version 2.4.0 introduces two new concepts: tax zones and Buchungsgruppen.' => '',
+  'Version 2.4.0 introduces two new concepts: tax zones and Buchungsgruppen.' => 'Version 2.4.0 hat zwei neue Konzepte eingeführt: Steuerzonen und Buchungsgruppen.',
   'View SEPA export'            => 'SEPA-Export-Details ansehen',
   'View warehouse content'      => 'Lagerbestand ansehen',
   'View/edit all employees sales documents' => 'Bearbeiten/ansehen der Verkaufsdokumente aller Mitarbeiter',
@@ -2114,7 +2116,7 @@ $self->{texts} = {
   'Weight unit'                 => 'Gewichtseinheit',
   'What <b>term</b> you are looking for?' => 'Nach welchem <b>Begriff</b> wollen Sie suchen?',
   'What type of item is this?'  => 'Was ist dieser Artikel?',
-  'Which is located at doc/Kivitendo-Dokumentation.pdf. Click here: ' => '',
+  'Which is located at doc/Kivitendo-Dokumentation.pdf. Click here: ' => 'Diese befindet sich unter doc/Kivitendo-Dokumentation.pdf. Klicken Sie hier:',
   'With Extension Of Time'      => 'mit Dauerfristverlängerung',
   'Workflow Delivery Order'     => 'Workflow Lieferschein',
   'Workflow purchase_order'     => 'Workflow Lieferantenauftrag',
@@ -2142,7 +2144,7 @@ $self->{texts} = {
   'You can either create a new database or chose an existing database.' => 'Sie können entweder eine neue Datenbank erstellen oder eine existierende auswählen.',
   'You can find information on the migration in the upgrade chapter of the documentation.' => 'Informationen über die Migration sind in der Upgrade Kapitel in der Dokumentation zu finden.',
   'You can only delete datasets that are not in use.' => 'Sie k&ouml;nnen nur Datenbanken l&ouml;schen, die momentan nicht in Benutzung sind.',
-  'You can use the following strings in the long description and all translations. They will be replaced by their actual values by kivitendo before they\'re output.' => '',
+  'You can use the following strings in the long description and all translations. They will be replaced by their actual values by kivitendo before they\'re output.' => 'Sie können die folgenden Begriffe in den Langtexten und allen Übersetzungen benutzen. Sie werden von kivitendo vor der Ausgabe durch ihren tatsächlichen Wert ersetzt.',
   'You cannot adjust the price for pricegroup "#1" by a negative percentage.' => 'Sie können den Preis für Preisgruppe "#1" um einen negativen Prozentwert anpassen.',
   'You cannot continue before all required modules are installed.' => 'Sie k&ouml;nnen nicht fortfahren, bevor alle ben&ouml;tigten Pakete installiert sind.',
   'You cannot continue until all unknown units have been mapped to known ones.' => 'Sie k&ouml;nnen nicht fortfahren, bis alle unbekannten Einheiten in neue Einheiten umgewandelt wurden.',
@@ -2157,7 +2159,7 @@ $self->{texts} = {
   'You have selected none of the invoices.' => 'Sie haben keine der Rechnungen ausgewählt.',
   'You have to chose a dimension unit and a service unit which will then be assigned to those entries.' => 'Sie m&uuml;ssen eine Ma&szlig;- und eine Dienstleistungseinheit ausw&auml;hlen, die diesen Waren und Dienstleistungen, denen noch keine Einheit zugeordnet ist, zugeordnet wird.',
   'You have to chose which unit to save for each of them.' => 'Sie m&uuml;ssen f&uuml;r jeden Artikel die neue Einheit ausw&auml;hlen.',
-  'You have to create at least one group, grant it access to kivitendo\'s functions and assign users to it.' => '',
+  'You have to create at least one group, grant it access to kivitendo\'s functions and assign users to it.' => 'Sie müssen mindestens eine Gruppe anlegen, ihr Zugriff auf kivitendo-Funktionen gewähren und ihr Benutzer zuweisen.',
   'You have to create new Buchungsgruppen for all the combinations of inventory, income and expense accounts that have been used already.' => 'Sie m&uuml;ssen neue Buchungsgruppen f&uuml;r alle Kombinationen aus Inventar-, Erl&ouml;s- und Aufwandskonto, die bereits benutzt wurden.',
   'You have to define a unit as a multiple of a smaller unit.' => 'Sie müssen Einheiten als ein Vielfaches einer kleineren Einheit eingeben.',
   'You have to enter a company name in your user preferences (see the "Program" menu, "Preferences").' => 'Sie müssen einen Firmennamen in Ihren Einstellungen angeben (siehe Menü "Programm", "Einstellungen").',
index 7005759..7f0397a 100644 (file)
@@ -50,7 +50,7 @@
    </tr>
   </table>
 
-  <input type="hidden" name="rpw" value="[% HTML.escape(rpw) %]">
+  <input type="hidden" name="{AUTH}admin_password" value="[% HTML.escape(admin_password) %]">
   <input type="hidden" name="action" value="create_auth_db">
 
   <input type="submit" class="submit" value="[% 'Create Dataset' | $T8 %]">
index 4fc5888..816d0b1 100644 (file)
@@ -32,7 +32,7 @@
 
  <form method="post" action="admin.pl">
 
-  <input type="hidden" name="rpw" value="[% HTML.escape(rpw) %]">
+  <input type="hidden" name="{AUTH}admin_password" value="[% HTML.escape(admin_password) %]">
   <input type="hidden" name="action" value="create_auth_tables">
 
   <input type="submit" class="submit" value="[% 'Create tables' | $T8 %]">
index b1a2daf..862d7de 100644 (file)
@@ -4,7 +4,7 @@
 [% UNLESS is_links %]
  <span class="frame-header-element frame-header-left">
     [<a href="JavaScript:Switch_Menu();" title="[% 'Switch Menu on / off' | $T8 %]">[% 'Menu' | $T8 %]</a>]
-    [<a href="controller.pl?action=LoginScreen/user_login" target="_blank" title="[% 'Open a further kivitendo Window or Tab' | $T8 %]">[% 'New Win/Tab' | $T8 %]</a>]
+    [<a href="controller.pl?action=LoginScreen/user_login" target="_blank" title="[% 'Open a further kivitendo window or tab' | $T8 %]">[% 'New window/tab' | $T8 %]</a>]
     [<a href="JavaScript:top.main_window.print();" title="[% 'Hardcopy' | $T8 %]">[% 'Print' | $T8 %]</a>]
     [<a href="Javascript:top.main_window.history.back();" title="[% 'Go one step back' | $T8 %]">[% 'Back' | $T8 %]</a>]
     [<a href="Javascript:top.main_window.history.forward();" title="[% 'Go one step forward' | $T8 %]">[% 'Fwd' | $T8 %]</a>]