1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger Accounting
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
17 # This program is free software; you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation; either version 2 of the License, or
20 # (at your option) any later version.
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write to the Free Software
28 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #=====================================================================
31 # user related functions
33 #=====================================================================
47 $main::lxdebug->enter_sub();
49 my ($type, $login) = @_;
54 my %user_data = $main::auth->read_user($login);
55 map { $self->{$_} = $user_data{$_} } keys %user_data;
58 $main::lxdebug->leave_sub();
64 $main::lxdebug->enter_sub();
71 # scan the locale directory and read in the LANGUAGE files
72 opendir(DIR, "locale");
74 my @dir = grep(!/(^\.\.?$|\..*)/, readdir(DIR));
76 foreach my $dir (@dir) {
77 next unless open(FH, "locale/$dir/LANGUAGE");
81 $cc{$dir} = "@language";
86 $main::lxdebug->leave_sub();
92 $main::lxdebug->enter_sub();
94 my ($self, $form) = @_;
100 if ($self->{login}) {
101 my %myconfig = $main::auth->read_user($self->{login});
103 # check if database is down
105 DBI->connect($myconfig{dbconnect}, $myconfig{dbuser},
107 or $self->error(DBI::errstr);
109 # we got a connection, check the version
110 my $query = qq|SELECT version FROM defaults|;
111 my $sth = $dbh->prepare($query);
112 $sth->execute || $form->dberror($query);
114 my ($dbversion) = $sth->fetchrow_array;
117 $self->create_employee_entry($form, $dbh, \%myconfig);
119 $self->create_schema_info_table($form, $dbh);
126 parse_dbupdate_controls($form, $myconfig{"dbdriver"});
128 map({ $form->{$_} = $myconfig{$_} }
129 qw(dbname dbhost dbport dbdriver dbuser dbpasswd dbconnect dateformat));
131 if (update_available($myconfig{"dbdriver"}, $dbversion) ||
132 update2_available($form, $controls)) {
134 $form->{"stylesheet"} = "lx-office-erp.css";
135 $form->{"title"} = $main::locale->text("Dataset upgrade");
137 print $form->parse_html_template("dbupgrade/header");
139 $form->{dbupdate} = "db$myconfig{dbname}";
140 $form->{ $form->{dbupdate} } = 1;
142 if ($form->{"show_dbupdate_warning"}) {
143 print $form->parse_html_template("dbupgrade/warning");
148 open(FH, ">$main::userspath/nologin") or die("$!");
150 # required for Oracle
151 $form->{dbdefault} = $sid;
153 # ignore HUP, QUIT in case the webserver times out
154 $SIG{HUP} = 'IGNORE';
155 $SIG{QUIT} = 'IGNORE';
157 $self->dbupdate($form);
158 $self->dbupdate2($form, $controls);
163 unlink("$main::userspath/nologin");
166 $self->{"menustyle"} eq "v3" ? "menuv3.pl" :
167 $self->{"menustyle"} eq "neu" ? "menunew.pl" :
168 $self->{"menustyle"} eq "xml" ? "menuXML.pl" :
171 print $form->parse_html_template("dbupgrade/footer", { "menufile" => $menufile });
178 $main::lxdebug->leave_sub();
184 $main::lxdebug->enter_sub();
186 my ($form, $db) = @_;
189 'Pg' => { 'yy-mm-dd' => 'set DateStyle to \'ISO\'',
190 'yyyy-mm-dd' => 'set DateStyle to \'ISO\'',
191 'mm/dd/yy' => 'set DateStyle to \'SQL, US\'',
192 'mm-dd-yy' => 'set DateStyle to \'POSTGRES, US\'',
193 'dd/mm/yy' => 'set DateStyle to \'SQL, EUROPEAN\'',
194 'dd-mm-yy' => 'set DateStyle to \'POSTGRES, EUROPEAN\'',
195 'dd.mm.yy' => 'set DateStyle to \'GERMAN\''
198 'yy-mm-dd' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'YY-MM-DD\'',
199 'yyyy-mm-dd' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'YYYY-MM-DD\'',
200 'mm/dd/yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'MM/DD/YY\'',
201 'mm-dd-yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'MM-DD-YY\'',
202 'dd/mm/yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'DD/MM/YY\'',
203 'dd-mm-yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'DD-MM-YY\'',
204 'dd.mm.yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'DD.MM.YY\'',
207 $form->{dboptions} = $dboptions{ $form->{dbdriver} }{ $form->{dateformat} };
209 if ($form->{dbdriver} eq 'Pg') {
210 $form->{dbconnect} = "dbi:Pg:dbname=$db";
213 if ($form->{dbdriver} eq 'Oracle') {
214 $form->{dbconnect} = "dbi:Oracle:sid=$form->{sid}";
217 if ($form->{dbhost}) {
218 $form->{dbconnect} .= ";host=$form->{dbhost}";
220 if ($form->{dbport}) {
221 $form->{dbconnect} .= ";port=$form->{dbport}";
224 $main::lxdebug->leave_sub();
228 $main::lxdebug->enter_sub();
230 my @drivers = DBI->available_drivers();
232 $main::lxdebug->leave_sub();
234 return (grep { /(Pg|Oracle)/ } @drivers);
238 $main::lxdebug->enter_sub();
240 my ($self, $form) = @_;
245 $form->{dbdefault} = $form->{dbuser} unless $form->{dbdefault};
246 $form->{sid} = $form->{dbdefault};
247 &dbconnect_vars($form, $form->{dbdefault});
250 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
253 if ($form->{dbdriver} eq 'Pg') {
255 qq|SELECT datname FROM pg_database | .
256 qq|WHERE NOT datname IN ('template0', 'template1')|;
257 $sth = $dbh->prepare($query);
258 $sth->execute() || $form->dberror($query);
260 while (my ($db) = $sth->fetchrow_array) {
262 if ($form->{only_acc_db}) {
264 next if ($db =~ /^template/);
266 &dbconnect_vars($form, $db);
268 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
272 qq|SELECT tablename FROM pg_tables | .
273 qq|WHERE (tablename = 'defaults') AND (tableowner = ?)|;
274 my $sth = $dbh->prepare($query);
275 $sth->execute($form->{dbuser}) ||
276 $form->dberror($query . " ($form->{dbuser})");
278 if ($sth->fetchrow_array) {
279 push(@dbsources, $db);
285 push(@dbsources, $db);
289 if ($form->{dbdriver} eq 'Oracle') {
290 if ($form->{only_acc_db}) {
292 qq|SELECT owner FROM dba_objects | .
293 qq|WHERE object_name = 'DEFAULTS' AND object_type = 'TABLE'|;
295 $query = qq|SELECT username FROM dba_users|;
298 $sth = $dbh->prepare($query);
299 $sth->execute || $form->dberror($query);
301 while (my ($db) = $sth->fetchrow_array) {
302 push(@dbsources, $db);
309 $main::lxdebug->leave_sub();
315 $main::lxdebug->enter_sub();
317 my ($self, $form) = @_;
319 $form->{sid} = $form->{dbdefault};
320 &dbconnect_vars($form, $form->{dbdefault});
322 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
324 $form->{db} =~ s/\"//g;
326 'Pg' => qq|CREATE DATABASE "$form->{db}"|,
328 qq|CREATE USER "$form->{db}" DEFAULT TABLESPACE USERS | .
329 qq|TEMPORARY TABLESPACE TEMP IDENTIFIED BY "$form->{db}"|
336 push(@{$dboptions{"Pg"}}, "ENCODING = " . $dbh->quote($form->{"encoding"}))
337 if ($form->{"encoding"});
338 if ($form->{"dbdefault"}) {
339 my $dbdefault = $form->{"dbdefault"};
340 $dbdefault =~ s/[^a-zA-Z0-9_\-]//g;
341 push(@{$dboptions{"Pg"}}, "TEMPLATE = $dbdefault");
344 my $query = $dbcreate{$form->{dbdriver}};
345 $query .= " WITH " . join(" ", @{$dboptions{"Pg"}}) if (@{$dboptions{"Pg"}});
347 do_query($form, $dbh, $query);
349 if ($form->{dbdriver} eq 'Oracle') {
350 $query = qq|GRANT CONNECT, RESOURCE TO "$form->{db}"|;
351 do_query($form, $dbh, $query);
355 # setup variables for the new database
356 if ($form->{dbdriver} eq 'Oracle') {
357 $form->{dbuser} = $form->{db};
358 $form->{dbpasswd} = $form->{db};
361 &dbconnect_vars($form, $form->{db});
363 $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
366 my $db_charset = $Common::db_encoding_to_charset{$form->{encoding}};
367 $db_charset ||= Common::DEFAULT_CHARSET;
370 $self->process_query($form, $dbh, "sql/lx-office.sql", undef, $db_charset);
372 # load chart of accounts
373 $self->process_query($form, $dbh, "sql/$form->{chart}-chart.sql", undef, $db_charset);
375 $query = "UPDATE defaults SET coa = ?";
376 do_query($form, $dbh, $query, $form->{chart});
380 $main::lxdebug->leave_sub();
383 # Process a Perl script which updates the database.
384 # If the script returns 1 then the update was successful.
385 # Return code "2" means "needs more interaction; remove
386 # users/nologin and exit".
387 # All other return codes are fatal errors.
388 sub process_perl_script {
389 $main::lxdebug->enter_sub();
391 my ($self, $form, $dbh, $filename, $version_or_control, $db_charset) = @_;
393 my $fh = IO::File->new($filename, "r") or $form->error("$filename : $!\n");
395 my $file_charset = Common::DEFAULT_CHARSET;
397 if (ref($version_or_control) eq "HASH") {
398 $file_charset = $version_or_control->{charset};
403 next if !/^--\s*\@charset:\s*(.+)/;
407 $fh->seek(0, SEEK_SET);
410 my $contents = join "", <$fh>;
413 $db_charset ||= Common::DEFAULT_CHARSET;
415 my $iconv = SL::Iconv::get_converter($file_charset, $db_charset);
419 my %dbup_myconfig = ();
420 map({ $dbup_myconfig{$_} = $form->{$_}; }
421 qw(dbname dbuser dbpasswd dbhost dbport dbconnect));
423 my $nls_file = $filename;
424 $nls_file =~ s|.*/||;
425 $nls_file =~ s|.pl$||;
426 my $dbup_locale = Locale->new($main::language, $nls_file);
428 my $result = eval($contents);
435 if (!defined($result)) {
436 print $form->parse_html_template("dbupgrade/error",
437 { "file" => $filename,
440 } elsif (1 != $result) {
441 unlink("users/nologin") if (2 == $result);
445 if (ref($version_or_control) eq "HASH") {
446 $dbh->do("INSERT INTO schema_info (tag, login) VALUES (" .
447 $dbh->quote($version_or_control->{"tag"}) . ", " .
448 $dbh->quote($form->{"login"}) . ")");
449 } elsif ($version_or_control) {
450 $dbh->do("UPDATE defaults SET version = " .
451 $dbh->quote($version_or_control));
455 $main::lxdebug->leave_sub();
459 $main::lxdebug->enter_sub();
461 my ($self, $form, $dbh, $filename, $version_or_control, $db_charset) = @_;
463 my $fh = IO::File->new($filename, "r") or $form->error("$filename : $!\n");
468 my $file_charset = Common::DEFAULT_CHARSET;
471 next if !/^--\s*\@charset:\s*(.+)/;
475 $fh->seek(0, SEEK_SET);
477 $db_charset ||= Common::DEFAULT_CHARSET;
482 $_ = SL::Iconv::convert($file_charset, $db_charset, $_);
484 # Remove DOS and Unix style line endings.
490 for (my $i = 0; $i < length($_); $i++) {
491 my $char = substr($_, $i, 1);
493 # Are we inside a string?
495 if ($char eq $quote_chars[-1]) {
501 if (($char eq "'") || ($char eq "\"")) {
502 push(@quote_chars, $char);
504 } elsif ($char eq ";") {
506 # Query is complete. Send it.
508 $sth = $dbh->prepare($query);
509 if (!$sth->execute()) {
510 my $errstr = $dbh->errstr;
513 $form->dberror("The database update/creation did not succeed. " .
514 "The file ${filename} containing the following " .
515 "query failed:<br>${query}<br>" .
516 "The error message was: ${errstr}<br>" .
517 "All changes in that file have been reverted.");
530 if (ref($version_or_control) eq "HASH") {
531 $dbh->do("INSERT INTO schema_info (tag, login) VALUES (" .
532 $dbh->quote($version_or_control->{"tag"}) . ", " .
533 $dbh->quote($form->{"login"}) . ")");
534 } elsif ($version_or_control) {
535 $dbh->do("UPDATE defaults SET version = " .
536 $dbh->quote($version_or_control));
542 $main::lxdebug->leave_sub();
546 $main::lxdebug->enter_sub();
548 my ($self, $form) = @_;
549 $form->{db} =~ s/\"//g;
550 my %dbdelete = ('Pg' => qq|DROP DATABASE "$form->{db}"|,
551 'Oracle' => qq|DROP USER "$form->{db}" CASCADE|);
553 $form->{sid} = $form->{dbdefault};
554 &dbconnect_vars($form, $form->{dbdefault});
556 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
558 my $query = $dbdelete{$form->{dbdriver}};
559 do_query($form, $dbh, $query);
563 $main::lxdebug->leave_sub();
566 sub dbsources_unused {
567 $main::lxdebug->enter_sub();
569 my ($self, $form) = @_;
571 $form->{only_acc_db} = 1;
573 my %members = $main::auth->read_all_users();
574 my %dbexcl = map { $_ => 1 } grep { $_ } map { $_->{dbname} } values %members;
576 $dbexcl{$form->{dbdefault}} = 1;
577 $dbexcl{$main::auth->{DB_config}->{db}} = 1;
579 my @dbunused = grep { !$dbexcl{$_} } dbsources("", $form);
581 $main::lxdebug->leave_sub();
587 $main::lxdebug->enter_sub();
589 my ($self, $form) = @_;
591 my %members = $main::auth->read_all_users();
592 my $controls = parse_dbupdate_controls($form, $form->{dbdriver});
594 my ($query, $sth, %dbs_needing_updates);
596 foreach my $login (grep /[a-z]/, keys %members) {
597 my $member = $members{$login};
599 map { $form->{$_} = $member->{$_} } qw(dbname dbuser dbpasswd dbhost dbport);
600 dbconnect_vars($form, $form->{dbname});
602 my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd});
608 $query = qq|SELECT version FROM defaults|;
609 $sth = prepare_query($form, $dbh, $query);
610 if ($sth->execute()) {
611 ($version) = $sth->fetchrow_array();
616 next unless $version;
618 if (update_available($form->{dbdriver}, $version) || update2_available($form, $controls)) {
620 map { $dbinfo->{$_} = $member->{$_} } grep /^db/, keys %{ $member };
621 $dbs_needing_updates{$member->{dbhost} . "::" . $member->{dbname}} = $dbinfo;
625 $main::lxdebug->leave_sub();
627 return values %dbs_needing_updates;
631 $main::lxdebug->enter_sub(2);
633 my (@v, $version, $i);
635 @v = split(/\./, $_[0]);
636 while (scalar(@v) < 4) {
640 for ($i = 0; $i < 4; $i++) {
645 $main::lxdebug->leave_sub(2);
649 sub cmp_script_version {
650 my ($a_from, $a_to, $b_from, $b_to);
651 my ($i, $res_a, $res_b);
652 my ($my_a, $my_b) = ($a, $b);
654 $my_a =~ s/.*-upgrade-//;
656 $my_b =~ s/.*-upgrade-//;
658 ($my_a_from, $my_a_to) = split(/-/, $my_a);
659 ($my_b_from, $my_b_to) = split(/-/, $my_b);
661 $res_a = calc_version($my_a_from);
662 $res_b = calc_version($my_b_from);
664 if ($res_a == $res_b) {
665 $res_a = calc_version($my_a_to);
666 $res_b = calc_version($my_b_to);
669 return $res_a <=> $res_b;
672 sub update_available {
673 my ($dbdriver, $cur_version) = @_;
677 opendir SQLDIR, "sql/${dbdriver}-upgrade" || error("", "sql/${dbdriver}-upgrade: $!");
678 my @upgradescripts = grep /${dbdriver}-upgrade-\Q$cur_version\E.*\.(sql|pl)$/, readdir SQLDIR;
681 return ($#upgradescripts > -1);
684 sub create_schema_info_table {
685 $main::lxdebug->enter_sub();
687 my ($self, $form, $dbh) = @_;
689 my $query = "SELECT tag FROM schema_info LIMIT 1";
690 if (!$dbh->do($query)) {
693 qq|CREATE TABLE schema_info (| .
696 qq| itime timestamp DEFAULT now(), | .
697 qq| PRIMARY KEY (tag))|;
698 $dbh->do($query) || $form->dberror($query);
701 $main::lxdebug->leave_sub();
705 $main::lxdebug->enter_sub();
707 my ($self, $form) = @_;
711 $form->{sid} = $form->{dbdefault};
713 my @upgradescripts = ();
717 if ($form->{dbupdate}) {
719 # read update scripts into memory
720 opendir(SQLDIR, "sql/" . $form->{dbdriver} . "-upgrade")
721 or &error("", "sql/" . $form->{dbdriver} . "-upgrade : $!");
723 sort(cmp_script_version
724 grep(/$form->{dbdriver}-upgrade-.*?\.(sql|pl)$/,
729 my $db_charset = $main::dbcharset;
730 $db_charset ||= Common::DEFAULT_CHARSET;
732 foreach my $db (split(/ /, $form->{dbupdate})) {
734 next unless $form->{$db};
736 # strip db from dataset
738 &dbconnect_vars($form, $db);
741 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
744 $dbh->do($form->{dboptions}) if ($form->{dboptions});
747 $query = qq|SELECT version FROM defaults|;
748 my ($version) = selectrow_query($form, $dbh, $query);
750 next unless $version;
752 $version = calc_version($version);
754 foreach my $upgradescript (@upgradescripts) {
755 my $a = $upgradescript;
756 $a =~ s/^\Q$form->{dbdriver}\E-upgrade-|\.(sql|pl)$//g;
759 my ($mindb, $maxdb) = split /-/, $a;
760 my $str_maxdb = $maxdb;
761 $mindb = calc_version($mindb);
762 $maxdb = calc_version($maxdb);
764 next if ($version >= $maxdb);
766 # if there is no upgrade script exit
767 last if ($version < $mindb);
770 $main::lxdebug->message(DEBUG2, "Applying Update $upgradescript");
771 if ($file_type eq "sql") {
772 $self->process_query($form, $dbh, "sql/" . $form->{"dbdriver"} .
773 "-upgrade/$upgradescript", $str_maxdb, $db_charset);
775 $self->process_perl_script($form, $dbh, "sql/" . $form->{"dbdriver"} .
776 "-upgrade/$upgradescript", $str_maxdb, $db_charset);
788 $main::lxdebug->leave_sub();
794 $main::lxdebug->enter_sub();
796 my ($self, $form, $controls) = @_;
798 $form->{sid} = $form->{dbdefault};
800 my @upgradescripts = ();
801 my ($query, $sth, $tag);
804 @upgradescripts = sort_dbupdate_controls($controls);
806 my $db_charset = $main::dbcharset;
807 $db_charset ||= Common::DEFAULT_CHARSET;
809 foreach my $db (split / /, $form->{dbupdate}) {
811 next unless $form->{$db};
813 # strip db from dataset
815 &dbconnect_vars($form, $db);
818 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
821 $dbh->do($form->{dboptions}) if ($form->{dboptions});
823 map({ $_->{"applied"} = 0; } @upgradescripts);
825 $self->create_schema_info_table($form, $dbh);
827 $query = qq|SELECT tag FROM schema_info|;
828 $sth = $dbh->prepare($query);
829 $sth->execute() || $form->dberror($query);
830 while (($tag) = $sth->fetchrow_array()) {
831 $controls->{$tag}->{"applied"} = 1 if (defined($controls->{$tag}));
836 foreach (@upgradescripts) {
837 if (!$_->{"applied"}) {
843 next if ($all_applied);
845 foreach my $control (@upgradescripts) {
846 next if ($control->{"applied"});
848 $control->{description} = SL::Iconv::convert($control->{charset}, $db_charset, $control->{description});
850 $control->{"file"} =~ /\.(sql|pl)$/;
854 $main::lxdebug->message(DEBUG2, "Applying Update $control->{file}");
855 print $form->parse_html_template("dbupgrade/upgrade_message2", $control);
857 if ($file_type eq "sql") {
858 $self->process_query($form, $dbh, "sql/" . $form->{"dbdriver"} .
859 "-upgrade2/$control->{file}", $control, $db_charset);
861 $self->process_perl_script($form, $dbh, "sql/" . $form->{"dbdriver"} .
862 "-upgrade2/$control->{file}", $control, $db_charset);
871 $main::lxdebug->leave_sub();
876 sub update2_available {
877 $main::lxdebug->enter_sub();
879 my ($form, $controls) = @_;
881 map({ $_->{"applied"} = 0; } values(%{$controls}));
883 dbconnect_vars($form, $form->{"dbname"});
886 DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) ||
889 my ($query, $tag, $sth);
891 $query = qq|SELECT tag FROM schema_info|;
892 $sth = $dbh->prepare($query);
893 if ($sth->execute()) {
894 while (($tag) = $sth->fetchrow_array()) {
895 $controls->{$tag}->{"applied"} = 1 if (defined($controls->{$tag}));
901 map({ $main::lxdebug->leave_sub() and return 1 if (!$_->{"applied"}) }
902 values(%{$controls}));
904 $main::lxdebug->leave_sub();
909 $main::lxdebug->enter_sub();
913 # format dbconnect and dboptions string
914 dbconnect_vars($self, $self->{dbname});
916 map { $self->{$_} =~ s/\r//g; } qw(address signature);
918 $main::auth->save_user($self->{login}, map { $_, $self->{$_} } config_vars());
920 my $dbh = DBI->connect($self->{dbconnect}, $self->{dbuser}, $self->{dbpasswd});
922 $self->create_employee_entry($form, $dbh, $self);
926 $main::lxdebug->leave_sub();
929 sub create_employee_entry {
930 $main::lxdebug->enter_sub();
935 my $myconfig = shift;
937 # add login to employee table if it does not exist
938 # no error check for employee table, ignore if it does not exist
939 my ($login) = selectrow_query($form, $dbh, qq|SELECT id FROM employee WHERE login = ?|, $self->{login});
942 $query = qq|INSERT INTO employee (login, name, workphone, role) VALUES (?, ?, ?, ?)|;
943 do_query($form, $dbh, $query, ($self->{login}, $myconfig->{name}, $myconfig->{tel}, "user"));
946 $main::lxdebug->leave_sub();
950 $main::lxdebug->enter_sub();
952 my @conf = qw(acs address admin businessnumber company countrycode
953 currency dateformat dbconnect dbdriver dbhost dbport dboptions
954 dbname dbuser dbpasswd email fax name numberformat password
955 printer role sid signature stylesheet tel templates vclimit angebote
956 bestellungen rechnungen anfragen lieferantenbestellungen einkaufsrechnungen
957 taxnumber co_ustid duns menustyle template_format default_media
958 default_printer_id copies show_form_details favorites
959 pdonumber sdonumber);
961 $main::lxdebug->leave_sub();
967 $main::lxdebug->enter_sub();
969 my ($self, $msg) = @_;
971 $main::lxdebug->show_backtrace();
973 if ($ENV{HTTP_USER_AGENT}) {
974 print qq|Content-Type: text/html
976 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
978 <body bgcolor=ffffff>
980 <h2><font color=red>Error!</font></h2>
987 $main::lxdebug->leave_sub();