20e5be24dd765afa7022276303cc42206043def2
[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
40 use SL::Form;
41 use SL::User;
42 use SL::Common;
43
44 require "bin/mozilla/common.pl";
45
46 our $cgi = new CGI('');
47
48 $form = new Form;
49 $form->{"root"} = "root login";
50
51 $locale = new Locale $language, "admin";
52
53 # customization
54 if (-f "bin/mozilla/custom_$form->{script}") {
55   eval { require "bin/mozilla/custom_$form->{script}"; };
56   $form->error($@) if ($@);
57 }
58
59 $form->{stylesheet} = "lx-office-erp.css";
60 $form->{favicon}    = "favicon.ico";
61
62 if ($form->{action}) {
63
64
65   $subroutine = $locale->findsub($form->{action});
66
67   if ($subroutine eq 'login') {
68     if ($form->{rpw}) {
69       $form->{rpw} = crypt $form->{rpw}, "ro";
70     }
71   }
72
73   &check_password;
74
75   call_sub($subroutine);
76
77 } else {
78
79   # if there are no drivers bail out
80   $form->error($locale->text('No Database Drivers available!'))
81     unless (User->dbdrivers);
82
83   # create memberfile
84   if (!-f $memberfile) {
85     open(FH, ">$memberfile") or $form->error("$memberfile : $!");
86     print FH qq|# SQL-Ledger Accounting members
87
88 [root login]
89 password=
90
91 |;
92     close FH;
93   }
94
95   &adminlogin;
96
97 }
98
99 1;
100
101 # end
102
103 sub adminlogin {
104
105   $form->{title} =
106     qq|Lx-Office ERP $form->{version} | . $locale->text('Administration');
107
108   $form->header();
109   print $form->parse_html_template('admin/adminlogin');
110 }
111
112 sub login {
113   list_users();
114 }
115
116 sub list_users {
117
118   $form->error($locale->text('File locked!')) if (-f "${memberfile}.LCK");
119
120   open(FH, "$memberfile") or $form->error("$memberfile : $!");
121
122   my %members;
123
124   while (<FH>) {
125     chomp;
126
127     if (/^\[.*\]/) {
128       $login = $_;
129       $login =~ s/(\[|\])//g;
130
131       $members{$login} = { "login" => $login };
132     }
133
134     if (/^([a-z]+)=(.*)/) {
135       $members{$login}->{$1} = $2;
136     }
137   }
138
139   close(FH);
140
141   delete $members{"root login"};
142   map { $_->{templates} =~ s|.*/||; } values %members;
143
144   $form->{title}  = "Lx-Office ERP " . $locale->text('Administration');
145   $form->{LOCKED} = -e "$userspath/nologin";
146   $form->{MEMBERS} = [ @members{sort { lc $a cmp lc $b } keys %members} ];
147
148   $form->header();
149   print $form->parse_html_template("admin/list_users");
150 }
151
152 sub add_user {
153
154   $form->{title} =
155       "Lx-Office ERP "
156     . $locale->text('Administration') . " / "
157     . $locale->text('Add User');
158
159   $form->{Oracle_sid}    = $sid;
160   $form->{Oracle_dbport} = '1521';
161   $form->{Oracle_dbhost} = `hostname`;
162
163   if (-f "css/lx-office-erp.css") {
164     $myconfig->{stylesheet} = "lx-office-erp.css";
165   }
166
167   $myconfig->{vclimit}      = 200;
168   $myconfig->{countrycode}  = "de";
169   $myconfig->{numberformat} = "1000,00";
170   $myconfig->{dateformat}   = "dd.mm.yy";
171
172   &form_header;
173   &form_footer;
174
175 }
176
177 sub edit {
178
179   $form->{title} =
180       "Lx-Office ERP "
181     . $locale->text('Administration') . " / "
182     . $locale->text('Edit User');
183   $form->{edit} = 1;
184
185   &form_header;
186   &form_footer;
187
188 }
189
190 sub form_footer {
191
192   if ($form->{edit}) {
193     $delete =
194       qq|<input type=submit class=submit name=action value="|
195       . $locale->text('Delete') . qq|">
196 <input type=hidden name=edit value=1>|;
197   }
198
199   print qq|
200
201 <input name=callback type=hidden value="$form->{script}?action=list_users&rpw=$form->{rpw}">
202 <input type=hidden name=rpw value=$form->{rpw}>
203
204 <input type=submit class=submit name=action value="|
205     . $locale->text('Save') . qq|">
206 $delete
207
208 </form>
209
210 </body>
211 </html>
212 |;
213
214 }
215
216 sub form_header {
217
218   # if there is a login, get user
219   if ($form->{login}) {
220
221     # get user
222     $myconfig = new User "$memberfile", "$form->{login}";
223
224     $myconfig->{signature} =~ s/\\n/\r\n/g;
225     $myconfig->{address}   =~ s/\\n/\r\n/g;
226
227     # strip basedir from templates directory
228     $myconfig->{templates} =~ s/^$templates\///;
229
230     # $myconfig->{dbpasswd} = unpack 'u', $myconfig->{dbpasswd};
231   }
232
233   foreach $item (qw(mm-dd-yy mm/dd/yy dd-mm-yy dd/mm/yy dd.mm.yy yyyy-mm-dd)) {
234     $dateformat .=
235       ($item eq $myconfig->{dateformat})
236       ? "<option selected>$item\n"
237       : "<option>$item\n";
238   }
239
240   foreach $item (qw(1,000.00 1000.00 1.000,00 1000,00)) {
241     $numberformat .=
242       ($item eq $myconfig->{numberformat})
243       ? "<option selected>$item\n"
244       : "<option>$item\n";
245   }
246
247   %countrycodes = User->country_codes;
248   $countrycodes = "";
249   foreach $key (sort { $countrycodes{$a} cmp $countrycodes{$b} }
250                 keys %countrycodes
251     ) {
252     $countrycodes .=
253       ($myconfig->{countrycode} eq $key)
254       ? "<option selected value=$key>$countrycodes{$key}"
255       : "<option value=$key>$countrycodes{$key}";
256   }
257   $countrycodes = qq|<option value="">American English\n$countrycodes|;
258
259   # is there a templates basedir
260   if (!-d "$templates") {
261     $form->error(  $locale->text('Directory')
262                  . ": $templates "
263                  . $locale->text('does not exist'));
264   }
265
266   opendir TEMPLATEDIR, "$templates/." or $form->error("$templates : $!");
267   my @all = readdir(TEMPLATEDIR);
268   my @alldir = sort(grep({ -d "$templates/$_" && !/^\.\.?$/ } @all));
269   my @allhtml = sort(grep({ -f "$templates/$_" && /\.html$/ } @all));
270   closedir TEMPLATEDIR;
271
272   @alldir = grep !/\.(html|tex|sty|odt|xml|txb)$/, @alldir;
273   @alldir = grep !/^(webpages|\.svn)$/, @alldir;
274
275   @allhtml = reverse grep !/Default/, @allhtml;
276   push @allhtml, 'Default';
277   @allhtml = reverse @allhtml;
278
279   foreach $item (@alldir) {
280     if ($item eq $myconfig->{templates}) {
281       $usetemplates .= qq|<option selected>$item\n|;
282     } else {
283       $usetemplates .= qq|<option>$item\n|;
284     }
285   }
286
287   $lastitem = $allhtml[0];
288   $lastitem =~ s/-.*//g;
289   $mastertemplates = qq|<option>$lastitem\n|;
290   foreach $item (@allhtml) {
291     $item =~ s/-.*//g;
292
293     if ($item ne $lastitem) {
294       my $selected = $item eq "German" ? " selected" : "";
295       $mastertemplates .= qq|<option$selected>$item\n|;
296       $lastitem = $item;
297     }
298   }
299
300 #  opendir CSS, "css/.";
301 #  @all = grep /.*\.css$/, readdir CSS;
302 #  closedir CSS;
303
304 # css dir has styles that are not intended as general layouts.
305 # reverting to hardcoded list
306   @all = qw(lx-office-erp.css Win2000.css);
307
308   foreach $item (@all) {
309     if ($item eq $myconfig->{stylesheet}) {
310       $selectstylesheet .= qq|<option selected>$item\n|;
311     } else {
312       $selectstylesheet .= qq|<option>$item\n|;
313     }
314   }
315
316   $form->header;
317
318   if ($myconfig->{menustyle} eq "v3") {
319     $menustyle_v3 = "checked";
320   } elsif ($myconfig->{menustyle} eq "neu") {
321     $menustyle_neu = "checked";
322   } else {
323     $menustyle_old = "checked";
324   }
325
326   print qq|
327 <body class=admin>
328
329 <form method=post action=$form->{script}>
330
331 <table width=100%>
332   <tr class=listheading><th colspan=2>$form->{title}</th></tr>
333   <tr size=5></tr>
334   <tr valign=top>
335     <td>
336       <table>
337         <tr>
338           <th align=right>| . $locale->text('Login') . qq|</th>
339           <td><input name="login" value="$myconfig->{login}"></td>
340         </tr>
341         <tr>
342           <th align=right>| . $locale->text('Password') . qq|</th>
343           <td><input type="password" name="password" size="8" value="$myconfig->{password}"></td>
344           <input type="hidden" name="old_password" value="$myconfig->{password}">
345         </tr>
346         <tr>
347           <th align=right>| . $locale->text('Name') . qq|</th>
348           <td><input name="name" size="15" value="$myconfig->{name}"></td>
349         </tr>
350         <tr>
351           <th align=right>| . $locale->text('E-mail') . qq|</th>
352           <td><input name=email size=30 value="$myconfig->{email}"></td>
353         </tr>
354         <tr valign=top>
355           <th align=right>| . $locale->text('Signature') . qq|</th>
356           <td><textarea name=signature rows=3 cols=35>$myconfig->{signature}</textarea></td>
357         </tr>
358         <tr>
359           <th align=right>| . $locale->text('Phone') . qq|</th>
360           <td><input name=tel size=14 value="$myconfig->{tel}"></td>
361         </tr>
362         <tr>
363           <th align=right>| . $locale->text('Fax') . qq|</th>
364           <td><input name=fax size=14 value="$myconfig->{fax}"></td>
365         </tr>
366         <tr>
367           <th align=right>| . $locale->text('Company') . qq|</th>
368           <td><input name=company size=35 value="$myconfig->{company}"></td>
369         </tr>
370         <tr valign=top>
371           <th align=right>| . $locale->text('Address') . qq|</th>
372           <td><textarea name=address rows=4 cols=35>$myconfig->{address}</textarea></td>
373         </tr>
374         <tr valign=top>
375           <th align=right>| . $locale->text('Tax number') . qq|</th>
376           <td><input name=taxnumber size=14 value="$myconfig->{taxnumber}"></td>
377         </tr>
378         <tr valign=top>
379           <th align=right>| . $locale->text('Ust-IDNr') . qq|</th>
380           <td><input name=co_ustid size=14 value="$myconfig->{co_ustid}"></td>
381         </tr>
382         <tr valign=top>
383           <th align=right>| . $locale->text('DUNS-Nr') . qq|</th>
384           <td><input name=duns size=14 value="$myconfig->{duns}"></td>
385         </tr>
386       </table>
387     </td>
388     <td>
389       <table>
390         <tr>
391           <th align=right>| . $locale->text('Date Format') . qq|</th>
392           <td><select name=dateformat>$dateformat</select></td>
393         </tr>
394         <tr>
395           <th align=right>| . $locale->text('Number Format') . qq|</th>
396           <td><select name=numberformat>$numberformat</select></td>
397         </tr>
398         <tr>
399           <th align=right>| . $locale->text('Dropdown Limit') . qq|</th>
400           <td><input name=vclimit value="$myconfig->{vclimit}"></td>
401         </tr>
402         <tr>
403           <th align=right>| . $locale->text('Language') . qq|</th>
404           <td><select name=countrycode>$countrycodes</select></td>
405         </tr>
406         <tr>
407           <th align=right>| . $locale->text('Stylesheet') . qq|</th>
408           <td><select name=userstylesheet>$selectstylesheet</select></td>
409         </tr>
410         <tr>
411           <th align=right>| . $locale->text('Printer') . qq|</th>
412           <td><input name=printer size=20 value="$myconfig->{printer}"></td>
413         </tr>
414         <tr>
415           <th align=right>| . $locale->text('Use Templates') . qq|</th>
416           <td><select name=usetemplates>$usetemplates</select></td>
417         </tr>
418         <tr>
419           <th align=right>| . $locale->text('New Templates') . qq|</th>
420           <td><input name=newtemplates></td>
421         </tr>
422         <tr>
423           <th align=right>| . $locale->text('Setup Templates') . qq|</th>
424           <td><select name=mastertemplates>$mastertemplates</select></td>
425         </tr>
426        <tr>
427            <th align=right>| . $locale->text('Setup Menu') . qq|</th>
428            <td><input name=menustyle type=radio class=radio value=v3 $menustyle_v3>&nbsp;| .
429            $locale->text("Top (CSS)") . qq|
430            <input name=menustyle type=radio class=radio value=neu $menustyle_neu>&nbsp;| .
431            $locale->text("Top (Javascript)") . qq|
432            <input name=menustyle type=radio class=radio value=old $menustyle_old>&nbsp;| .
433            $locale->text("Old (on the side)") . qq|
434            </td>
435          </tr>
436         <input type=hidden name=templates value=$myconfig->{templates}>
437       </table>
438     </td>
439   </tr>
440   <tr class=listheading>
441     <th colspan=2>| . $locale->text('Database') . qq|</th>
442   </tr>|;
443
444   # list section for database drivers
445   foreach $item (User->dbdrivers) {
446
447     print qq|
448   <tr>
449     <td colspan=2>
450       <table>
451         <tr>|;
452
453     $checked = "";
454     if ($myconfig->{dbdriver} eq $item) {
455       map { $form->{"${item}_$_"} = $myconfig->{$_} }
456         qw(dbhost dbport dbuser dbpasswd dbname sid);
457       $checked = "checked";
458     }
459
460     print qq|
461           <th align=right>| . $locale->text('Driver') . qq|</th>
462           <td><input name="dbdriver" type="radio" class="radio" value="$item" $checked>&nbsp;$item</td>
463           <th align=right>| . $locale->text('Host') . qq|</th>
464           <td><input name="${item}_dbhost" size=30 value="$form->{"${item}_dbhost"}"></td>
465         </tr>
466         <tr>|;
467
468     if ($item eq 'Pg') {
469     
470       print qq|
471           <th align=right>| . $locale->text('Dataset') . qq|</th>
472           <td><input name="Pg_dbname" size="15" value="$form->{Pg_dbname}"></td>
473           <th align=right>| . $locale->text('Port') . qq|</th>
474           <td><input name="Pg_dbport" size="4" value="$form->{Pg_dbport}"></td>
475         </tr>
476         <tr>
477           <th align=right>| . $locale->text('User') . qq|</th>
478           <td><input name="${item}_dbuser" size=15 value="$form->{"${item}_dbuser"}"></td>
479           <th align=right>| . $locale->text('Password') . qq|</th>
480           <td><input name="${item}_dbpasswd" type=password size=10 value="$form->{"${item}_dbpasswd"}"></td>
481         </tr>|;
482
483     }
484
485     if ($item eq 'Oracle') {
486       print qq|
487           <th align=right>SID</th>
488           <td><input name=Oracle_sid value=$form->{Oracle_sid}></td>
489           <th align=right>| . $locale->text('Port') . qq|</th>
490           <td><input name=Oracle_dbport size=4 value=$form->{Oracle_dbport}></td>
491         </tr>
492         <tr>
493           <th align=right>| . $locale->text('Dataset') . qq|</th>
494           <td><input name="${item}_dbuser" size=15 value=$form->{"${item}_dbuser"}></td>
495           <th align=right>| . $locale->text('Password') . qq|</th>
496           <td><input name="${item}_dbpasswd" type=password size=10 value="$form->{"${item}_dbpasswd"}"></td>
497
498         </tr>|;
499     }
500
501     print qq|
502         <input type="hidden" name="old_dbpasswd" value="$myconfig->{dbpasswd}">
503       </table>
504     </td>
505   </tr>
506   <tr>
507     <td colspan=2><hr size=2 noshade></td>
508   </tr>
509 |;
510
511   }
512
513   # access control
514   open(FH, $menufile) or $form->error("$menufile : $!");
515
516   # scan for first menu level
517   @a = <FH>;
518   close(FH);
519
520   foreach $item (@a) {
521     next unless $item =~ /\[/;
522     next if $item =~ /\#/;
523
524     $item =~ s/(\[|\])//g;
525     chop $item;
526
527     if ($item =~ /--/) {
528       ($level, $menuitem) = split /--/, $item, 2;
529     } else {
530       $level    = $item;
531       $menuitem = $item;
532       push @acsorder, $item;
533     }
534
535     push @{ $acs{$level} }, $menuitem;
536
537   }
538
539   %role = ('admin'      => $locale->text('Administrator'),
540            'user'       => $locale->text('User'),
541            'manager'    => $locale->text('Manager'),
542            'supervisor' => $locale->text('Supervisor'));
543
544   $selectrole = "";
545   foreach $item (qw(user supervisor manager admin)) {
546     $selectrole .=
547       ($myconfig->{role} eq $item)
548       ? "<option selected value=$item>$role{$item}\n"
549       : "<option value=$item>$role{$item}\n";
550   }
551
552   print qq|
553   <tr class=listheading>
554     <th colspan=2>| . $locale->text('Access Control') . qq|</th>
555   </tr>
556   <tr>
557     <td><select name=role>$selectrole</select></td>
558   </tr>
559 |;
560
561   foreach $item (split(/;/, $myconfig->{acs})) {
562     ($key, $value) = split /--/, $item, 2;
563     $excl{$key}{$value} = 1;
564   }
565
566   foreach $key (@acsorder) {
567
568     $checked = "checked";
569     if ($form->{login}) {
570       $checked = ($excl{$key}{$key}) ? "" : "checked";
571     }
572
573     # can't have variable names with spaces
574     # the 1 is for apache 2
575     $item = $form->escape("${key}--$key", 1);
576
577     $acsheading = $key;
578     $acsheading =~ s/ /&nbsp;/g;
579
580     $acsheading = qq|
581     <th align=left><input name="$item" class=checkbox type=checkbox value=1 $checked>&nbsp;$acsheading</th>\n|;
582     $menuitems .= "$item;";
583     $acsdata = "
584     <td>";
585
586     foreach $item (@{ $acs{$key} }) {
587       next if ($key eq $item);
588
589       $checked = "checked";
590       if ($form->{login}) {
591         $checked = ($excl{$key}{$item}) ? "" : "checked";
592       }
593
594       $acsitem = $form->escape("${key}--$item", 1);
595
596       $acsdata .= qq|
597     <br><input name="$acsitem" class=checkbox type=checkbox value=1 $checked>&nbsp;$item|;
598       $menuitems .= "$acsitem;";
599     }
600
601     $acsdata .= "
602     </td>";
603
604     print qq|
605   <tr valign=top>$acsheading $acsdata
606   </tr>
607 |;
608   }
609
610   print qq|<input type=hidden name=acs value="$menuitems">
611 |;
612   if ($webdav) {
613     @webdavdirs =
614       qw(angebote bestellungen rechnungen anfragen lieferantenbestellungen einkaufsrechnungen);
615     foreach $directory (@webdavdirs) {
616       if ($myconfig->{$directory}) {
617         $webdav{"${directory}c"} = "checked";
618       } else {
619         $webdav{"${directory}c"} = "";
620       }
621     }
622     print qq|
623    <tr>
624     <td colspan=2><hr size=3 noshade></td>
625   </tr>
626   <tr class=listheading>
627     <th colspan=2>| . $locale->text('WEBDAV-Zugriff') . qq|</th>
628   </tr>
629   <table width=100%>
630         <tr>
631         <td><input name=angebote class=checkbox type=checkbox value=1 $webdav{angebotec}>&nbsp;Angebot</td>
632         <td><input name=bestellungen class=checkbox type=checkbox value=1 $webdav{bestellungenc}>&nbsp;Bestellung</td>
633         <td><input name=rechnungen class=checkbox type=checkbox value=1 $webdav{rechnungenc}>&nbsp;Rechnung</td>
634         </tr>
635         <tr>
636         <td><input name=anfragen class=checkbox type=checkbox value=1 $webdav{anfragenc}>&nbsp;Angebot</td>
637         <td><input name=lieferantenbestellungen class=checkbox type=checkbox value=1 $webdav{lieferantenbestellungenc}>&nbsp;Lieferantenbestellung</td>
638         <td><input name=einkaufsrechnungen class=checkbox type=checkbox value=1 $webdav{einkaufsrechnungenc}>&nbsp;Einkaufsrechnung</td>
639         </tr>
640   </table>
641   <tr>
642     <td colspan=2><hr size=3 noshade></td>
643   </tr>
644 |;
645   }
646   print qq|
647 </table>
648 </div>
649 |;
650
651 }
652
653 sub save {
654
655   # no driver checked
656   $form->error($locale->text('Database Driver not checked!'))
657     unless $form->{dbdriver};
658
659   # no spaces allowed in login name
660   ($form->{login}) = split / /, $form->{login};
661
662   $form->isblank("login", $locale->text('Login name missing!'));
663
664   # check for duplicates
665   if (!$form->{edit}) {
666     $temp = new User "$memberfile", "$form->{login}";
667
668     if ($temp->{login}) {
669       $form->error("$form->{login} " . $locale->text('is already a member!'));
670     }
671   }
672
673   # no spaces allowed in directories
674   ($form->{newtemplates}) = split / /, $form->{newtemplates};
675
676   if ($form->{newtemplates}) {
677     $form->{templates} = $form->{newtemplates};
678   } else {
679     $form->{templates} =
680       ($form->{usetemplates}) ? $form->{usetemplates} : $form->{login};
681   }
682
683   # is there a basedir
684   if (!-d "$templates") {
685     $form->error(  $locale->text('Directory')
686                  . ": $templates "
687                  . $locale->text('does not exist'));
688   }
689
690   # add base directory to $form->{templates}
691   $form->{templates} = "$templates/$form->{templates}";
692
693   $myconfig = new User "$memberfile", "$form->{login}";
694
695   # redo acs variable and delete all the acs codes
696   @acs = split(/;/, $form->{acs});
697
698   $form->{acs} = "";
699   foreach $item (@acs) {
700     $item = $form->escape($item, 1);
701
702     if (!$form->{$item}) {
703       $form->{acs} .= $form->unescape($form->unescape($item)) . ";";
704     }
705     delete $form->{$item};
706   }
707
708   # check which database was filled in
709   if ($form->{dbdriver} eq 'Oracle') {
710     $form->{sid}      = $form->{Oracle_sid},;
711     $form->{dbhost}   = $form->{Oracle_dbhost},;
712     $form->{dbport}   = $form->{Oracle_dbport};
713     $form->{dbpasswd} = $form->{Oracle_dbpasswd};
714     $form->{dbuser}   = $form->{Oracle_dbuser};
715     $form->{dbname}   = $form->{Oracle_dbuser};
716
717     $form->isblank("dbhost", $locale->text('Hostname missing!'));
718     $form->isblank("dbport", $locale->text('Port missing!'));
719     $form->isblank("dbuser", $locale->text('Dataset missing!'));
720   }
721   if ($form->{dbdriver} eq 'Pg') {
722     $form->{dbhost}   = $form->{Pg_dbhost};
723     $form->{dbport}   = $form->{Pg_dbport};
724     $form->{dbpasswd} = $form->{Pg_dbpasswd};
725     $form->{dbuser}   = $form->{Pg_dbuser};
726     $form->{dbname}   = $form->{Pg_dbname};
727
728     $form->isblank("dbname", $locale->text('Dataset missing!'));
729     $form->isblank("dbuser", $locale->text('Database User missing!'));
730   }
731
732   if ($webdav) {
733     @webdavdirs =
734       qw(angebote bestellungen rechnungen anfragen lieferantenbestellungen einkaufsrechnungen);
735     foreach $directory (@webdavdirs) {
736       if ($form->{$directory}) {
737         $form->{$directory} = $form->{$directory};
738       } else {
739         $form->{$directory} = 0;
740       }
741     }
742   }
743
744   foreach $item (keys %{$form}) {
745     $myconfig->{$item} = $form->{$item};
746   }
747
748   delete $myconfig->{stylesheet};
749   if ($form->{userstylesheet}) {
750     $myconfig->{stylesheet} = $form->{userstylesheet};
751   }
752
753   $myconfig->save_member($memberfile, $userspath);
754
755   if ($webdav) {
756     @webdavdirs =
757       qw(angebote bestellungen rechnungen anfragen lieferantenbestellungen einkaufsrechnungen);
758     foreach $directory (@webdavdirs) {
759       $file = "webdav/" . $directory . "/webdav-user";
760       if ($form->{$directory}) {
761         if (open(HTACCESS, "$file")) {
762           while (<HTACCESS>) {
763             ($login, $password) = split(/:/, $_);
764             if ($login ne $form->{login}) {
765               $newfile .= $_;
766             }
767           }
768           close(HTACCESS);
769         }
770         open(HTACCESS, "> $file") or die "cannot open $file $!\n";
771         $newfile .= $myconfig->{login} . ":" . $myconfig->{password} . "\n";
772         print(HTACCESS $newfile);
773         close(HTACCESS);
774       } else {
775         $form->{$directory} = 0;
776         if (open(HTACCESS, "$file")) {
777           while (<HTACCESS>) {
778             ($login, $password) = split(/:/, $_);
779             if ($login ne $form->{login}) {
780               $newfile .= $_;
781             }
782           }
783           close(HTACCESS);
784         }
785         open(HTACCESS, "> $file") or die "cannot open $file $!\n";
786         print(HTACCESS $newfile);
787         close(HTACCESS);
788       }
789     }
790   }
791
792   $form->{templates}       =~ s|.*/||;
793   $form->{mastertemplates} =~ s|.*/||;
794
795   # create user template directory and copy master files
796   if (!-d "$form->{templates}") {
797     umask(002);
798
799     if (mkdir "$form->{templates}", oct("771")) {
800
801       umask(007);
802
803       # copy templates to the directory
804       opendir TEMPLATEDIR, "$templates/." or $form - error("$templates : $!");
805       @templates = grep /$form->{mastertemplates}.*?\.(html|tex|sty|xml|txb)$/,
806         readdir TEMPLATEDIR;
807       closedir TEMPLATEDIR;
808
809       foreach $file (@templates) {
810         open(TEMP, "$templates/$file")
811           or $form->error("$templates/$file : $!");
812
813         $file =~ s/$form->{mastertemplates}-//;
814         open(NEW, ">$form->{templates}/$file")
815           or $form->error("$form->{templates}/$file : $!");
816
817         while ($line = <TEMP>) {
818           print NEW $line;
819         }
820         close(TEMP);
821         close(NEW);
822       }
823     } else {
824       $form->error("$!: $form->{templates}");
825     }
826   }
827
828   $form->redirect($locale->text('User saved!'));
829
830 }
831
832 sub delete {
833
834   $form->{templates} =
835     ($form->{templates})
836     ? "$templates/$form->{templates}"
837     : "$templates/$form->{login}";
838
839   $form->error($locale->text('File locked!')) if (-f ${memberfile} . LCK);
840   open(FH, ">${memberfile}.LCK") or $form->error("${memberfile}.LCK : $!");
841   close(FH);
842
843   open(CONF, "+<$memberfile") or $form->error("$memberfile : $!");
844
845   @config = <CONF>;
846
847   seek(CONF, 0, 0);
848   truncate(CONF, 0);
849
850   while ($line = shift @config) {
851
852     if ($line =~ /^\[/) {
853       last if ($line =~ /\[$form->{login}\]/);
854       $login = &login_name($line);
855     }
856
857     if ($line =~ /^templates=/) {
858       $user{$login} = &get_value($line);
859     }
860
861     print CONF $line;
862   }
863
864   # remove everything up to next login or EOF
865   # and save template variable
866   while ($line = shift @config) {
867     if ($line =~ /^templates=/) {
868       $templatedir = &get_value($line);
869     }
870     last if ($line =~ /^\[/);
871   }
872
873   # this one is either the next login or EOF
874   print CONF $line;
875
876   $login = &login_name($line);
877
878   while ($line = shift @config) {
879     if ($line =~ /^\[/) {
880       $login = &login_name($line);
881     }
882
883     if ($line =~ /^templates=/) {
884       $user{$login} = &get_value($line);
885     }
886
887     print CONF $line;
888   }
889
890   close(CONF);
891   unlink "${memberfile}.LCK";
892
893   # scan %user for $templatedir
894   foreach $login (keys %user) {
895     last if ($found = ($templatedir eq $user{$login}));
896   }
897
898   # if found keep directory otherwise delete
899   if (!$found) {
900
901     # delete it if there is a template directory
902     $dir = "$form->{templates}";
903     if (-d "$dir") {
904       unlink <$dir/*.html>;
905       unlink <$dir/*.tex>;
906       unlink <$dir/*.sty>;
907       rmdir "$dir";
908     }
909   }
910
911   # delete config file for user
912   unlink "$userspath/$form->{login}.conf";
913
914   $form->redirect($locale->text('User deleted!'));
915
916 }
917
918 sub login_name {
919   my $login = shift;
920
921   $login =~ s/\[\]//g;
922   return ($login) ? $login : undef;
923
924 }
925
926 sub get_value {
927   my $line = shift;
928
929   my ($null, $value) = split(/=/, $line, 2);
930
931   # remove comments
932   $value =~ s/\s#.*//g;
933
934   # remove any trailing whitespace
935   $value =~ s/^\s*(.*?)\s*$/$1/;
936
937   $value;
938 }
939
940 sub change_admin_password {
941
942   $form->{title} =
943       qq|Lx-Office ERP |
944     . $locale->text('Administration') . " / "
945     . $locale->text('Change Admin Password');
946
947   $form->header();
948   print $form->parse_html_template("admin/change_admin_password");
949 }
950
951 sub change_password {
952   if ($form->{"password"} ne $form->{"password_again"}) {
953     $form->{title} =
954       qq|Lx-Office ERP |
955       . $locale->text('Administration') . " / "
956       . $locale->text('Change Admin Password');
957
958     $form->header();
959     $form->error($locale->text("The passwords do not match."));
960   }
961
962   $root->{password} = $form->{password};
963
964   $root->{'root login'} = 1;
965   $root->save_member($memberfile);
966
967   $form->{callback} =
968     "$form->{script}?action=list_users&rpw=$root->{password}";
969
970   $form->redirect($locale->text('Password changed!'));
971 }
972
973 sub check_password {
974   $root = new User "$memberfile", $form->{root};
975
976   if (!defined($root->{password}) || ($root->{password} ne $form->{rpw})) {
977     $form->error($locale->text('Incorrect Password!'));
978   }
979
980 }
981
982 sub pg_database_administration {
983
984   $form->{dbdriver} = 'Pg';
985   &dbselect_source;
986
987 }
988
989 sub oracle_database_administration {
990
991   $form->{dbdriver} = 'Oracle';
992   &dbselect_source;
993
994 }
995
996 sub dbdriver_defaults {
997
998   # load some defaults for the selected driver
999   %driverdefaults = (
1000                      'Pg' => { dbport        => '5432',
1001                                dbuser        => 'postgres',
1002                                dbdefault     => 'template1',
1003                                dbhost        => 'localhost',
1004                                connectstring => $locale->text('Connect to')
1005                      },
1006                      'Oracle' => { dbport        => '1521',
1007                                    dbuser        => 'oralin',
1008                                    dbdefault     => $sid,
1009                                    dbhost        => `hostname`,
1010                                    connectstring => 'SID'
1011                      });
1012
1013   map { $form->{$_} = $driverdefaults{ $form->{dbdriver} }{$_} }
1014     keys %{ $driverdefaults{Pg} };
1015
1016 }
1017
1018 sub dbselect_source {
1019
1020   &dbdriver_defaults;
1021
1022   $msg{Pg} =
1023     $locale->text(
1024     'Leave host and port field empty unless you want to make a remote connection.'
1025     );
1026   $msg{Oracle} =
1027     $locale->text(
1028            'You must enter a host and port for local and remote connections!');
1029
1030   $form->{title} =
1031     "Lx-Office ERP / " . $locale->text('Database Administration');
1032
1033   $form->header;
1034
1035   print qq|
1036 <body class=admin>
1037
1038
1039 <center>
1040 <h2>$form->{title}</h2>
1041
1042 <form method=post action=$form->{script}>
1043
1044 <table>
1045 <tr><td>
1046
1047 <table>
1048
1049   <tr class=listheading>
1050     <th colspan=4>| . $locale->text('Database') . qq|</th>
1051   </tr>
1052
1053 <input type=hidden name=dbdriver value=$form->{dbdriver}>
1054
1055   <tr><td>
1056    <table>
1057
1058   <tr>
1059
1060     <th align=right>| . $locale->text('Host') . qq|</th>
1061     <td><input name=dbhost size=25 value=$form->{dbhost}></td>
1062     <th align=right>| . $locale->text('Port') . qq|</th>
1063     <td><input name=dbport size=5 value=$form->{dbport}></td>
1064
1065   </tr>
1066
1067   <tr>
1068
1069     <th align=right>| . $locale->text('User') . qq|</th>
1070     <td><input name="dbuser" size="10" value="$form->{dbuser}"></td>
1071     <th align=right>| . $locale->text('Password') . qq|</th>
1072     <td><input type="password" name="dbpasswd" size="10"></td>
1073
1074   </tr>
1075
1076   <tr>
1077
1078     <th align=right>$form->{connectstring}</th>
1079     <td colspan=3><input name=dbdefault size=10 value=$form->{dbdefault}></td>
1080
1081   </tr>
1082
1083 </table>
1084
1085 </td></tr>
1086 </table>
1087
1088 <input name=callback type=hidden value="$form->{script}?action=list_users&rpw=$form->{rpw}">
1089 <input type=hidden name=rpw value=$form->{rpw}>
1090
1091 <br>
1092
1093 <input type=submit class=submit name=action value="|
1094     . $locale->text('Create Dataset') . qq|">|;
1095 # Vorübergehend Deaktiviert
1096 # <input type=submit class=submit name=action value="|
1097 #     . $locale->text('Update Dataset') . qq|">
1098 print qq| <input type=submit class=submit name=action value="|
1099     . $locale->text('Delete Dataset') . qq|">
1100
1101 </form>
1102
1103 </td></tr>
1104 </table>
1105
1106 <p>|
1107     . $locale->text(
1108     'This is a preliminary check for existing sources. Nothing will be created or deleted at this stage!'
1109     )
1110
1111     . qq|
1112 <br>$msg{$form->{dbdriver}}
1113
1114
1115 </body>
1116 </html>
1117 |;
1118
1119 }
1120
1121 sub continue {
1122   call_sub($form->{"nextsub"});
1123 }
1124
1125 sub update_dataset {
1126
1127   %needsupdate = User->dbneedsupdate(\%$form);
1128
1129   $form->{title} =
1130       "Lx-Office ERP "
1131     . $locale->text('Database Administration') . " / "
1132     . $locale->text('Update Dataset');
1133
1134   $form->header;
1135
1136   print qq|
1137 <body class=admin>
1138
1139
1140 <center>
1141 <h2>$form->{title}</h2>
1142 |;
1143   my $field_id = 0;
1144   foreach $key (sort keys %needsupdate) {
1145     if ($needsupdate{$key} ne $form->{dbversion}) {
1146       $upd .= qq|<input id="$field_id" name="db$key" type="checkbox" value="1" checked> $key\n|;
1147       $form->{dbupdate} .= "db$key ";
1148       $field_id++;
1149     }
1150   }
1151
1152   chop $form->{dbupdate};
1153
1154   if ($form->{dbupdate}) {
1155
1156     print qq|
1157 <table width=100%>
1158 <form method=post action=$form->{script}>
1159
1160 <input type=hidden name="dbdriver"  value="$form->{dbdriver}">
1161 <input type=hidden name="dbhost"    value="$form->{dbhost}">
1162 <input type=hidden name="dbport"    value="$form->{dbport}">
1163 <input type=hidden name="dbuser"    value="$form->{dbuser}">
1164 <input type=hidden name="dbpasswd"  value="$form->{dbpasswd}">
1165 <input type=hidden name="dbdefault" value="$form->{dbdefault}">
1166
1167 <tr class=listheading>
1168   <th>| . $locale->text('The following Datasets need to be updated') . qq|</th>
1169 </tr>
1170 <tr>
1171 <td>
1172
1173 $upd
1174
1175 </td>
1176 </tr>
1177 <tr>
1178 <td>
1179
1180 <input name=dbupdate type=hidden value="$form->{dbupdate}">
1181
1182 <input name=callback type=hidden value="$form->{script}?action=list_users&rpw=$form->{rpw}">
1183
1184 <input type=hidden name=rpw value=$form->{rpw}>
1185
1186 <input type=hidden name=nextsub value=dbupdate>
1187
1188 <hr size=3 noshade>
1189
1190 <br>
1191 <input type=submit class=submit name=action value="|
1192       . $locale->text('Continue') . qq|">
1193
1194 </td></tr>
1195 </table>
1196 </form>
1197 |;
1198
1199   } else {
1200
1201     print $locale->text('All Datasets up to date!');
1202
1203   }
1204
1205   print qq|
1206
1207 </body>
1208 </html>
1209 |;
1210
1211 }
1212
1213 sub dbupdate {
1214   $form->{"stylesheet"} = "lx-office-erp.css";
1215   $form->{"title"} = $main::locale->text("Dataset upgrade");
1216   $form->header();
1217   my $dbname =
1218     join(" ",
1219          map({ s/\s//g; s/^db//; $_; }
1220              grep({ $form->{$_} }
1221                   split(/\s+/, $form->{"dbupdate"}))));
1222   print($form->parse_html_template("dbupgrade/header",
1223                                    { "dbname" => $dbname }));
1224
1225   User->dbupdate(\%$form);
1226
1227   print qq|
1228 <hr>
1229
1230 | . $locale->text('Dataset updated!') . qq|
1231
1232 <br>
1233
1234 <a id="enddatasetupdate" href="admin.pl?action=login&| .
1235 join("&", map({ "$_=" . $form->escape($form->{$_}); } qw(rpw))) .
1236 qq|">| . $locale->text("Continue") . qq|</a>|;
1237
1238 }
1239
1240 sub create_dataset {
1241   $form->{dbsources} = join " ", map { "[${_}]" } sort User->dbsources(\%$form);
1242
1243   $form->{CHARTS} = [];
1244
1245   opendir SQLDIR, "sql/." or $form - error($!);
1246   foreach $item (sort grep /-chart\.sql\z/, readdir SQLDIR) {
1247     next if ($item eq 'Default-chart.sql');
1248     $item =~ s/-chart\.sql//;
1249     push @{ $form->{CHARTS} }, { "name"     => $item,
1250                                  "selected" => $item eq "Germany-DATEV-SKR03EU" };
1251   }
1252   closedir SQLDIR;
1253
1254   my $default_charset = $dbcharset;
1255   $default_charset ||= Common::DEFAULT_CHARSET;
1256
1257   $form->{DBENCODINGS} = [];
1258
1259   foreach my $encoding (@Common::db_encodings) {
1260     push @{ $form->{DBENCODINGS} }, { "dbencoding" => $encoding->{dbencoding},
1261                                       "label"      => $encoding->{label},
1262                                       "selected"   => $encoding->{charset} eq $default_charset };
1263   }
1264
1265   $form->{title} =
1266       "Lx-Office ERP "
1267     . $locale->text('Database Administration') . " / "
1268     . $locale->text('Create Dataset');
1269
1270   $form->header();
1271   print $form->parse_html_template("admin/create_dataset");
1272 }
1273
1274 sub dbcreate {
1275   $form->isblank("db", $locale->text('Dataset missing!'));
1276
1277   User->dbcreate(\%$form);
1278
1279   $form->{title} =
1280       "Lx-Office ERP "
1281     . $locale->text('Database Administration') . " / "
1282     . $locale->text('Create Dataset');
1283
1284   $form->header();
1285   print $form->parse_html_template("admin/dbcreate");
1286 }
1287
1288 sub delete_dataset {
1289   @dbsources = User->dbsources_unused(\%$form, $memberfile);
1290   $form->error($locale->text('Nothing to delete!')) unless @dbsources;
1291
1292   $form->{title} =
1293       "Lx-Office ERP "
1294     . $locale->text('Database Administration') . " / "
1295     . $locale->text('Delete Dataset');
1296   $form->{DBSOURCES} = [ map { { "name", $_ } } sort @dbsources ];
1297
1298   $form->header();
1299   print $form->parse_html_template("admin/delete_dataset");
1300 }
1301
1302 sub dbdelete {
1303
1304   if (!$form->{db}) {
1305     $form->error($locale->text('No Dataset selected!'));
1306   }
1307
1308   User->dbdelete(\%$form);
1309
1310   $form->{title} =
1311       "Lx-Office ERP "
1312     . $locale->text('Database Administration') . " / "
1313     . $locale->text('Delete Dataset');
1314
1315   $form->header();
1316   print $form->parse_html_template("admin/dbdelete");
1317 }
1318
1319 sub unlock_system {
1320
1321   unlink "$userspath/nologin";
1322
1323   $form->{callback} =
1324     "$form->{script}?action=list_users&rpw=$root->{password}";
1325
1326   $form->redirect($locale->text('Lockfile removed!'));
1327
1328 }
1329
1330 sub lock_system {
1331
1332   open(FH, ">$userspath/nologin")
1333     or $form->error($locale->text('Cannot create Lock!'));
1334   close(FH);
1335
1336   $form->{callback} =
1337     "$form->{script}?action=list_users&rpw=$root->{password}";
1338
1339   $form->redirect($locale->text('Lockfile created!'));
1340
1341 }