9805417cdfe6e7e87f891e7c6a4c17eb0f274371
[kivitendo-erp.git] / bin / mozilla / admin.pl
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 #
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (c) 2002
10 #
11 #  Author: Dieter Simader
12 #   Email: dsimader@sql-ledger.org
13 #     Web: http://www.sql-ledger.org
14 #
15 #
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
20 #
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #======================================================================
29 #
30 # setup module
31 # add/edit/delete users
32 #
33 #======================================================================
34
35 $menufile = "menu.ini";
36
37 use DBI;
38 use CGI;
39 use POSIX qw(strftime);
40 use IO::File;
41 use Fcntl;
42 use English qw(-no_match_vars);
43 use Sys::Hostname;
44
45 use SL::Form;
46 use SL::Mailer;
47 use SL::User;
48 use SL::Common;
49 use SL::Inifile;
50 use SL::DBUpgrade2;
51
52 require "bin/mozilla/common.pl";
53
54 our $cgi = new CGI('');
55
56 $form = new Form;
57 $form->{"root"} = "root login";
58
59 $locale = new Locale $language, "admin";
60
61 # customization
62 if (-f "bin/mozilla/custom_$form->{script}") {
63   eval { require "bin/mozilla/custom_$form->{script}"; };
64   $form->error($@) if ($@);
65 }
66
67 $form->{stylesheet} = "lx-office-erp.css";
68 $form->{favicon}    = "favicon.ico";
69
70 if ($form->{action}) {
71
72
73   $subroutine = $locale->findsub($form->{action});
74
75   if ($subroutine eq 'login') {
76     if ($form->{rpw}) {
77       $form->{rpw} = crypt $form->{rpw}, "ro";
78     }
79   }
80
81   check_password();
82
83   call_sub($subroutine);
84
85 } else {
86
87   # if there are no drivers bail out
88   $form->error($locale->text('No Database Drivers available!'))
89     unless (User->dbdrivers);
90
91   # create memberfile
92   if (!-f $memberfile) {
93     open(FH, ">$memberfile") or $form->error("$memberfile : $!");
94     print FH qq|# SQL-Ledger Accounting members
95
96 [root login]
97 password=
98
99 |;
100     close FH;
101   }
102
103   adminlogin();
104
105 }
106
107 1;
108
109 # end
110
111 sub adminlogin {
112
113   $form->{title} =
114     qq|Lx-Office ERP $form->{version} | . $locale->text('Administration');
115
116   $form->header();
117   print $form->parse_html_template('admin/adminlogin');
118 }
119
120 sub login {
121   list_users();
122 }
123
124 sub list_users {
125
126   $form->error($locale->text('File locked!')) if (-f "${memberfile}.LCK");
127
128   open(FH, "$memberfile") or $form->error("$memberfile : $!");
129
130   my %members;
131
132   while (<FH>) {
133     chomp;
134
135     if (/^\[.*\]/) {
136       $login = $_;
137       $login =~ s/(\[|\])//g;
138
139       $members{$login} = { "login" => $login };
140     }
141
142     if (/^([a-z]+)=(.*)/) {
143       $members{$login}->{$1} = $2;
144     }
145   }
146
147   close(FH);
148
149   delete $members{"root login"};
150   map { $_->{templates} =~ s|.*/||; } values %members;
151
152   $form->{title}  = "Lx-Office ERP " . $locale->text('Administration');
153   $form->{LOCKED} = -e "$userspath/nologin";
154   $form->{MEMBERS} = [ @members{sort { lc $a cmp lc $b } keys %members} ];
155
156   $form->header();
157   print $form->parse_html_template("admin/list_users");
158 }
159
160 sub add_user {
161
162   $form->{title} =
163       "Lx-Office ERP "
164     . $locale->text('Administration') . " / "
165     . $locale->text('Add User');
166
167   my $myconfig = {
168     "vclimit"      => 200,
169     "countrycode"  => "de",
170     "numberformat" => "1000,00",
171     "dateformat"   => "dd.mm.yy",
172     "stylesheet"   => "lx-office-erp.css",
173     "menustyle"    => "v3",
174   };
175
176   edit_user_form($myconfig);
177 }
178
179 sub edit {
180
181   $form->{title} =
182       "Lx-Office ERP "
183     . $locale->text('Administration') . " / "
184     . $locale->text('Edit User');
185   $form->{edit} = 1;
186
187   $form->isblank("login", $locale->text("The login is missing."));
188
189   # get user
190   my $myconfig = new User "$memberfile", "$form->{login}";
191
192   $myconfig->{signature} =~ s/\\n/\r\n/g;
193   $myconfig->{address}   =~ s/\\n/\r\n/g;
194
195   # strip basedir from templates directory
196   $myconfig->{templates} =~ s|.*/||;
197
198   edit_user_form($myconfig);
199 }
200
201 sub edit_user_form {
202   my ($myconfig) = @_;
203
204   my @valid_dateformats = qw(mm-dd-yy mm/dd/yy dd-mm-yy dd/mm/yy dd.mm.yy yyyy-mm-dd);
205   $form->{ALL_DATEFORMATS} = [ map { { "format" => $_, "selected" => $_ eq $myconfig->{dateformat} } } @valid_dateformats ];
206
207   my @valid_numberformats = qw(1,000.00 1000.00 1.000,00 1000,00);
208   $form->{ALL_NUMBERFORMATS} = [ map { { "format" => $_, "selected" => $_ eq $myconfig->{numberformat} } } @valid_numberformats ];
209
210   %countrycodes = User->country_codes;
211   $form->{ALL_COUNTRYCODES} = [];
212   foreach $countrycode (sort { $countrycodes{$a} cmp $countrycodes{$b} } keys %countrycodes) {
213     push @{ $form->{ALL_COUNTRYCODES} }, { "value"    => $countrycode,
214                                            "name"     => $countrycodes{$countrycode},
215                                            "selected" => $countrycode eq $myconfig->{countrycode} };
216   }
217
218   # is there a templates basedir
219   if (!-d "$templates") {
220     $form->error(sprintf($locale->text("The directory %s does not exist."), $templates));
221   }
222
223   opendir TEMPLATEDIR, "$templates/." or $form->error("$templates : $!");
224   my @all     = readdir(TEMPLATEDIR);
225   my @alldir  = sort grep { -d "$templates/$_" && !/^\.\.?$/ } @all;
226   my @allhtml = sort grep { -f "$templates/$_" && /\.html$/ } @all;
227   closedir TEMPLATEDIR;
228
229   @alldir = grep !/\.(html|tex|sty|odt|xml|txb)$/, @alldir;
230   @alldir = grep !/^(webpages|\.svn)$/, @alldir;
231
232   @allhtml = reverse grep !/Default/, @allhtml;
233   push @allhtml, 'Default';
234   @allhtml = reverse @allhtml;
235
236   $form->{ALL_TEMPLATES} = [ map { { "name", => $_, "selected" => $_ eq $myconfig->{templates} } } @alldir ];
237
238   $lastitem = $allhtml[0];
239   $lastitem =~ s/-.*//g;
240   $form->{ALL_MASTER_TEMPLATES} = [ { "name" => $lastitem, "selected" => $lastitem eq "German" } ];
241   foreach $item (@allhtml) {
242     $item =~ s/-.*//g;
243     next if ($item eq $lastitem);
244
245     push @{ $form->{ALL_MASTER_TEMPLATES} }, { "name" => $item, "selected" => $item eq "German" };
246     $lastitem = $item;
247   }
248
249   # css dir has styles that are not intended as general layouts.
250   # reverting to hardcoded list
251   $form->{ALL_STYLESHEETS} = [ map { { "name" => $_, "selected" => $_ eq $myconfig->{stylesheet} } } qw(lx-office-erp.css Win2000.css) ];
252
253   $form->{"menustyle_" . $myconfig->{menustyle} } = 1;
254
255   map { $form->{"myc_${_}"} = $myconfig->{$_} } keys %{ $myconfig };
256
257   # access control
258   my @acsorder = ();
259   my %acs      = ();
260   my %excl     = ();
261   open(FH, $menufile) or $form->error("$menufile : $!");
262
263   while ($item = <FH>) {
264     next unless $item =~ /\[/;
265     next if $item =~ /\#/;
266
267     $item =~ s/(\[|\])//g;
268     chomp $item;
269
270     my ($level, $menuitem);
271
272     if ($item =~ /--/) {
273       ($level, $menuitem) = split /--/, $item, 2;
274     } else {
275       $level    = $item;
276       $menuitem = $item;
277       push @acsorder, $item;
278     }
279
280     $acs{$level} ||= [];
281     push @{ $acs{$level} }, $menuitem;
282
283   }
284
285   foreach $item (split(/;/, $myconfig->{acs})) {
286     ($key, $value) = split /--/, $item, 2;
287     $excl{$key}{$value} = 1;
288   }
289
290   $form->{ACLS}    = [];
291   $form->{all_acs} = "";
292
293   foreach $key (@acsorder) {
294     my $acl = { "checked" => $form->{login} ? !$excl{$key}->{$key} : 1,
295                 "name"    => "${key}--${key}",
296                 "title"   => $key,
297                 "SUBACLS" => [], };
298     $form->{all_acs} .= "${key}--${key};";
299
300     foreach $item (@{ $acs{$key} }) {
301       next if ($key eq $item);
302
303       my $subacl = { "checked" => $form->{login} ? !$excl{$key}->{$item} : 1,
304                      "name"    => "${key}--${item}",
305                      "title"   => $item };
306       push @{ $acl->{SUBACLS} }, $subacl;
307       $form->{all_acs} .= "${key}--${item};";
308     }
309     push @{ $form->{ACLS} }, $acl;
310   }
311
312   chop $form->{all_acs};
313
314   $form->header();
315   print $form->parse_html_template("admin/edit_user");
316 }
317
318 sub save {
319
320   $form->{dbdriver} = 'Pg';
321
322   # no spaces allowed in login name
323   ($form->{login}) = split / /, $form->{login};
324
325   $form->isblank("login", $locale->text('Login name missing!'));
326
327   # check for duplicates
328   if (!$form->{edit}) {
329     $temp = new User "$memberfile", "$form->{login}";
330
331     if ($temp->{login}) {
332       $form->error("$form->{login} " . $locale->text('is already a member!'));
333     }
334   }
335
336   # no spaces allowed in directories
337   ($form->{newtemplates}) = split / /, $form->{newtemplates};
338
339   if ($form->{newtemplates}) {
340     $form->{templates} = $form->{newtemplates};
341   } else {
342     $form->{templates} =
343       ($form->{usetemplates}) ? $form->{usetemplates} : $form->{login};
344   }
345
346   # is there a basedir
347   if (!-d "$templates") {
348     $form->error(sprintf($locale->text("The directory %s does not exist."), $templates));
349   }
350
351   # add base directory to $form->{templates}
352   $form->{templates} =~ s|.*/||;
353   $form->{templates} =  "$templates/$form->{templates}";
354
355   $myconfig = new User "$memberfile", "$form->{login}";
356
357   # redo acs variable and delete all the acs codes
358   my @acs;
359   foreach $item (split m|;|, $form->{all_acs}) {
360     my $name =  "ACS_${item}";
361     $name    =~ s| |+|g;
362     push @acs, $item if !$form->{$name};
363     delete $form->{$name};
364   }
365   $form->{acs} = join ";", @acs;
366
367   $form->isblank("dbname", $locale->text('Dataset missing!'));
368   $form->isblank("dbuser", $locale->text('Database User missing!'));
369
370   foreach $item (keys %{$form}) {
371     $myconfig->{$item} = $form->{$item};
372   }
373
374   delete $myconfig->{stylesheet};
375   if ($form->{userstylesheet}) {
376     $myconfig->{stylesheet} = $form->{userstylesheet};
377   }
378
379   $myconfig->save_member($memberfile, $userspath);
380
381   if ($webdav) {
382     @webdavdirs =
383       qw(angebote bestellungen rechnungen anfragen lieferantenbestellungen einkaufsrechnungen);
384     foreach $directory (@webdavdirs) {
385       $file = "webdav/" . $directory . "/webdav-user";
386       if ($form->{$directory}) {
387         if (open(HTACCESS, "$file")) {
388           while (<HTACCESS>) {
389             ($login, $password) = split(/:/, $_);
390             if ($login ne $form->{login}) {
391               $newfile .= $_;
392             }
393           }
394           close(HTACCESS);
395         }
396         open(HTACCESS, "> $file") or die "cannot open $file $!\n";
397         $newfile .= $myconfig->{login} . ":" . $myconfig->{password} . "\n";
398         print(HTACCESS $newfile);
399         close(HTACCESS);
400       } else {
401         $form->{$directory} = 0;
402         if (open(HTACCESS, "$file")) {
403           while (<HTACCESS>) {
404             ($login, $password) = split(/:/, $_);
405             if ($login ne $form->{login}) {
406               $newfile .= $_;
407             }
408           }
409           close(HTACCESS);
410         }
411         open(HTACCESS, "> $file") or die "cannot open $file $!\n";
412         print(HTACCESS $newfile);
413         close(HTACCESS);
414       }
415     }
416   }
417
418   $form->{templates}       =~ s|.*/||;
419   $form->{templates}       =  "${templates}/$form->{templates}";
420   $form->{mastertemplates} =~ s|.*/||;
421
422   # create user template directory and copy master files
423   if (!-d "$form->{templates}") {
424     umask(002);
425
426     if (mkdir "$form->{templates}", oct("771")) {
427
428       umask(007);
429
430       # copy templates to the directory
431       opendir TEMPLATEDIR, "$templates/." or $form - error("$templates : $!");
432       @templates = grep /$form->{mastertemplates}.*?\.(html|tex|sty|xml|txb)$/,
433         readdir TEMPLATEDIR;
434       closedir TEMPLATEDIR;
435
436       foreach $file (@templates) {
437         open(TEMP, "$templates/$file")
438           or $form->error("$templates/$file : $!");
439
440         $file =~ s/$form->{mastertemplates}-//;
441         open(NEW, ">$form->{templates}/$file")
442           or $form->error("$form->{templates}/$file : $!");
443
444         while ($line = <TEMP>) {
445           print NEW $line;
446         }
447         close(TEMP);
448         close(NEW);
449       }
450     } else {
451       $form->error("$!: $form->{templates}");
452     }
453   }
454
455   $form->redirect($locale->text('User saved!'));
456
457 }
458
459 sub delete {
460   $form->error($locale->text('File locked!')) if (-f ${memberfile} . LCK);
461   open(FH, ">${memberfile}.LCK") or $form->error("${memberfile}.LCK : $!");
462   close(FH);
463
464   my $members = Inifile->new($memberfile);
465   my $templates = $members->{$form->{login}}->{templates};
466   delete $members->{$form->{login}};
467   $members->write();
468   unlink "${memberfile}.LCK";
469
470   if ($templates) {
471     my $templates_in_use = 0;
472     foreach $login (keys %{ $members }) {
473       next if $login =~ m/^[A-Z]+$/;
474       next if $members->{$login}->{templates} ne $templates;
475       $templates_in_use = 1;
476       last;
477     }
478
479     if (!$templates_in_use && -d $templates) {
480       unlink <$templates/*>;
481       rmdir $templates;
482     }
483   }
484
485   # delete config file for user
486   unlink "$userspath/$form->{login}.conf";
487
488   $form->redirect($locale->text('User deleted!'));
489
490 }
491
492 sub login_name {
493   my $login = shift;
494
495   $login =~ s/\[\]//g;
496   return ($login) ? $login : undef;
497
498 }
499
500 sub get_value {
501   my $line = shift;
502
503   my ($null, $value) = split(/=/, $line, 2);
504
505   # remove comments
506   $value =~ s/\s#.*//g;
507
508   # remove any trailing whitespace
509   $value =~ s/^\s*(.*?)\s*$/$1/;
510
511   $value;
512 }
513
514 sub change_admin_password {
515
516   $form->{title} =
517       qq|Lx-Office ERP |
518     . $locale->text('Administration') . " / "
519     . $locale->text('Change Admin Password');
520
521   $form->header();
522   print $form->parse_html_template("admin/change_admin_password");
523 }
524
525 sub change_password {
526   if ($form->{"password"} ne $form->{"password_again"}) {
527     $form->{title} =
528       qq|Lx-Office ERP |
529       . $locale->text('Administration') . " / "
530       . $locale->text('Change Admin Password');
531
532     $form->header();
533     $form->error($locale->text("The passwords do not match."));
534   }
535
536   $root->{password} = $form->{password};
537
538   $root->{'root login'} = 1;
539   $root->save_member($memberfile);
540
541   $form->{callback} =
542     "$form->{script}?action=list_users&rpw=$root->{password}";
543
544   $form->redirect($locale->text('Password changed!'));
545 }
546
547 sub check_password {
548   $root = new User "$memberfile", $form->{root};
549
550   if (!defined($root->{password}) || ($root->{password} ne $form->{rpw})) {
551     $form->error($locale->text('Incorrect Password!'));
552   }
553
554 }
555
556 sub pg_database_administration {
557
558   $form->{dbdriver} = 'Pg';
559   dbselect_source();
560
561 }
562
563 sub dbselect_source {
564   $form->{dbport}    = '5432';
565   $form->{dbuser}    = 'postgres';
566   $form->{dbdefault} = 'template1';
567   $form->{dbhost}    = 'localhost';
568
569   $form->{title}     = "Lx-Office ERP / " . $locale->text('Database Administration');
570
571   $form->{ALLOW_DBBACKUP} = "$pg_dump_exe" ne "DISABLED";
572
573   $form->header();
574   print $form->parse_html_template("admin/dbadmin");
575 }
576
577 sub continue {
578   call_sub($form->{"nextsub"});
579 }
580
581 sub update_dataset {
582   $form->{title} =
583       "Lx-Office ERP "
584     . $locale->text('Database Administration') . " / "
585     . $locale->text('Update Dataset');
586
587   my @need_updates      = User->dbneedsupdate($form);
588   $form->{NEED_UPDATES} = \@need_updates;
589   $form->{ALL_UPDATED}  = !scalar @need_updates;
590
591   $form->header();
592   print $form->parse_html_template("admin/update_dataset");
593 }
594
595 sub dbupdate {
596   $form->{stylesheet} = "lx-office-erp.css";
597   $form->{title}      = $locale->text("Dataset upgrade");
598   $form->header();
599
600   my $rowcount           = $form->{rowcount} * 1;
601   my @update_rows        = grep { $form->{"update_$_"} } (1 .. $rowcount);
602   $form->{NOTHING_TO_DO} = !scalar @update_rows;
603   my $saved_form         = save_form();
604
605   $| = 1;
606
607   print $form->parse_html_template("admin/dbupgrade_all_header");
608
609   foreach my $i (@update_rows) {
610     restore_form($saved_form);
611
612     map { $form->{$_} = $form->{"${_}_${i}"} } qw(dbname dbdriver dbhost dbport dbuser dbpasswd);
613
614     my $controls = parse_dbupdate_controls($form, $form->{dbdriver});
615
616     print $form->parse_html_template("admin/dbupgrade_header");
617
618     $form->{dbupdate}        = $form->{dbname};
619     $form->{$form->{dbname}} = 1;
620
621     User->dbupdate($form);
622     User->dbupdate2($form, $controls);
623
624     print $form->parse_html_template("admin/dbupgrade_footer");
625   }
626
627   print $form->parse_html_template("admin/dbupgrade_all_done");
628 }
629
630 sub create_dataset {
631   $form->{dbsources} = join " ", map { "[${_}]" } sort User->dbsources(\%$form);
632
633   $form->{CHARTS} = [];
634
635   opendir SQLDIR, "sql/." or $form - error($!);
636   foreach $item (sort grep /-chart\.sql\z/, readdir SQLDIR) {
637     next if ($item eq 'Default-chart.sql');
638     $item =~ s/-chart\.sql//;
639     push @{ $form->{CHARTS} }, { "name"     => $item,
640                                  "selected" => $item eq "Germany-DATEV-SKR03EU" };
641   }
642   closedir SQLDIR;
643
644   my $default_charset = $dbcharset;
645   $default_charset ||= Common::DEFAULT_CHARSET;
646
647   $form->{DBENCODINGS} = [];
648
649   foreach my $encoding (@Common::db_encodings) {
650     push @{ $form->{DBENCODINGS} }, { "dbencoding" => $encoding->{dbencoding},
651                                       "label"      => $encoding->{label},
652                                       "selected"   => $encoding->{charset} eq $default_charset };
653   }
654
655   $form->{title} =
656       "Lx-Office ERP "
657     . $locale->text('Database Administration') . " / "
658     . $locale->text('Create Dataset');
659
660   $form->header();
661   print $form->parse_html_template("admin/create_dataset");
662 }
663
664 sub dbcreate {
665   $form->isblank("db", $locale->text('Dataset missing!'));
666
667   User->dbcreate(\%$form);
668
669   $form->{title} =
670       "Lx-Office ERP "
671     . $locale->text('Database Administration') . " / "
672     . $locale->text('Create Dataset');
673
674   $form->header();
675   print $form->parse_html_template("admin/dbcreate");
676 }
677
678 sub delete_dataset {
679   @dbsources = User->dbsources_unused(\%$form, $memberfile);
680   $form->error($locale->text('Nothing to delete!')) unless @dbsources;
681
682   $form->{title} =
683       "Lx-Office ERP "
684     . $locale->text('Database Administration') . " / "
685     . $locale->text('Delete Dataset');
686   $form->{DBSOURCES} = [ map { { "name", $_ } } sort @dbsources ];
687
688   $form->header();
689   print $form->parse_html_template("admin/delete_dataset");
690 }
691
692 sub dbdelete {
693
694   if (!$form->{db}) {
695     $form->error($locale->text('No Dataset selected!'));
696   }
697
698   User->dbdelete(\%$form);
699
700   $form->{title} =
701       "Lx-Office ERP "
702     . $locale->text('Database Administration') . " / "
703     . $locale->text('Delete Dataset');
704   $form->header();
705   print $form->parse_html_template("admin/dbdelete");
706 }
707
708 sub backup_dataset {
709   $form->{title} =
710       "Lx-Office ERP "
711     . $locale->text('Database Administration') . " / "
712     . $locale->text('Backup Dataset');
713
714   if ("$pg_dump_exe" eq "DISABLED") {
715     $form->error($locale->text('Database backups and restorations are disabled in lx-erp.conf.'));
716   }
717
718   my @dbsources         = sort User->dbsources($form);
719   $form->{DATABASES}    = [ map { { "dbname" => $_ } } @dbsources ];
720   $form->{NO_DATABASES} = !scalar @dbsources;
721
722   my $username  = getpwuid $UID || "unknown-user";
723   my $hostname  = hostname() || "unknown-host";
724   $form->{from} = "Lx-Office Admin <${username}\@${hostname}>";
725
726   $form->header();
727   print $form->parse_html_template("admin/backup_dataset");
728 }
729
730 sub backup_dataset_start {
731   $form->{title} =
732       "Lx-Office ERP "
733     . $locale->text('Database Administration') . " / "
734     . $locale->text('Backup Dataset');
735
736   $pg_dump_exe ||= "pg_dump";
737
738   if ("$pg_dump_exe" eq "DISABLED") {
739     $form->error($locale->text('Database backups and restorations are disabled in lx-erp.conf.'));
740   }
741
742   $form->isblank("dbname", $locale->text('The dataset name is missing.'));
743   $form->isblank("to", $locale->text('The email address is missing.')) if $form->{destination} eq "email";
744
745   my $tmpdir = "/tmp/lx_office_backup_" . Common->unique_id();
746   mkdir $tmpdir, 0700 || $form->error($locale->text('A temporary directory could not be created:') . " $!");
747
748   my $pgpass = IO::File->new("${tmpdir}/.pgpass", O_WRONLY | O_CREAT, 0600);
749
750   if (!$pgpass) {
751     unlink $tmpdir;
752     $form->error($locale->text('A temporary file could not be created:') . " $!");
753   }
754
755   print $pgpass "$form->{dbhost}:$form->{dbport}:$form->{dbname}:$form->{dbuser}:$form->{dbpasswd}\n";
756   $pgpass->close();
757
758   $ENV{HOME} = $tmpdir;
759
760   my @args = ("-Ft", "-c", "-o", "-h", $form->{dbhost}, "-U", $form->{dbuser});
761   push @args, ("-p", $form->{dbport}) if ($form->{dbport});
762   push @args, $form->{dbname};
763
764   my $cmd  = "${pg_dump_exe} " . join(" ", map { s/\\/\\\\/g; s/\"/\\\"/g; $_ } @args);
765   my $name = "dataset_backup_$form->{dbname}_" . strftime("%Y%m%d", localtime()) . ".tar";
766
767   if ($form->{destination} ne "email") {
768     my $in = IO::File->new("$cmd |");
769
770     if (!$in) {
771       unlink "${tmpdir}/.pgpass";
772       rmdir $tmpdir;
773
774       $form->error($locale->text('The pg_dump process could not be started.'));
775     }
776
777     print "content-type: application/x-tar\n";
778     print "content-disposition: attachment; filename=\"${name}\"\n\n";
779
780     while (my $line = <$in>) {
781       print $line;
782     }
783
784     $in->close();
785
786     unlink "${tmpdir}/.pgpass";
787     rmdir $tmpdir;
788
789   } else {
790     my $tmp = $tmpdir . "/dump_" . Common::unique_id();
791
792     if (system("$cmd > $tmp") != 0) {
793       unlink "${tmpdir}/.pgpass", $tmp;
794       rmdir $tmpdir;
795
796       $form->error($locale->text('The pg_dump process could not be started.'));
797     }
798
799     my $mail = new Mailer;
800
801     map { $mail->{$_} = $form->{$_} } qw(from to cc subject message);
802
803     $mail->{charset}     = $dbcharset ? $dbcharset : Common::DEFAULT_CHARSET;
804     $mail->{attachments} = [ { "filename" => $tmp, "name" => $name } ];
805     $mail->send();
806
807     unlink "${tmpdir}/.pgpass", $tmp;
808     rmdir $tmpdir;
809
810     $form->{title} =
811         "Lx-Office ERP "
812       . $locale->text('Database Administration') . " / "
813       . $locale->text('Backup Dataset');
814
815     $form->header();
816     print $form->parse_html_template("admin/backup_dataset_email_done");
817   }
818 }
819
820 sub restore_dataset {
821   $form->{title} =
822       "Lx-Office ERP "
823     . $locale->text('Database Administration') . " / "
824     . $locale->text('Restore Dataset');
825
826   if ("$pg_dump_exe" eq "DISABLED") {
827     $form->error($locale->text('Database backups and restorations are disabled in lx-erp.conf.'));
828   }
829 }
830
831 sub unlock_system {
832
833   unlink "$userspath/nologin";
834
835   $form->{callback} =
836     "$form->{script}?action=list_users&rpw=$root->{password}";
837
838   $form->redirect($locale->text('Lockfile removed!'));
839
840 }
841
842 sub lock_system {
843
844   open(FH, ">$userspath/nologin")
845     or $form->error($locale->text('Cannot create Lock!'));
846   close(FH);
847
848   $form->{callback} =
849     "$form->{script}?action=list_users&rpw=$root->{password}";
850
851   $form->redirect($locale->text('Lockfile created!'));
852
853 }