From: Sven Schöling Date: Mon, 28 Feb 2011 13:16:47 +0000 (+0100) Subject: Merge branch 'master' of git@lx-office.linet-services.de:lx-office-erp X-Git-Tag: release-2.6.3~61^2~1 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/c6d0de695657e132931e883c08f1436974bc22f2?hp=5af819906ae8e00533c4cdfc16a5f410e5116eb9 Merge branch 'master' of git@lx-office.linet-services.de:lx-office-erp --- diff --git a/SL/Auth.pm b/SL/Auth.pm index 3b7a6287f..cd16c8e0b 100644 --- a/SL/Auth.pm +++ b/SL/Auth.pm @@ -136,11 +136,11 @@ sub authenticate_root { sub authenticate { $main::lxdebug->enter_sub(); - my $self = shift; + my ($self, $login, $password) = @_; $main::lxdebug->leave_sub(); - my $result = $self->{authenticator}->authenticate(@_); + my $result = $login ? $self->{authenticator}->authenticate($login, $password) : ERR_USER; return OK if $result eq OK; sleep 5; return $result; @@ -166,7 +166,7 @@ sub dbconnect { $main::lxdebug->message(LXDebug->DEBUG1, "Auth::dbconnect DSN: $dsn"); - $self->{dbh} = DBI->connect($dsn, $cfg->{user}, $cfg->{password}, { pg_enable_utf8 => $::locale->is_utf8, AutoCommit => 0 }); + $self->{dbh} = DBI->connect($dsn, $cfg->{user}, $cfg->{password}, { pg_enable_utf8 => $::locale->is_utf8, AutoCommit => 1 }); if (!$may_fail && !$self->{dbh}) { $main::form->error($main::locale->text('The connection to the authentication database failed:') . "\n" . $DBI::errstr); @@ -306,6 +306,8 @@ sub save_user { my ($sth, $query, $user_id); + $dbh->begin_work; + $query = qq|SELECT id FROM auth."user" WHERE login = ?|; ($user_id) = selectrow_query($form, $dbh, $query, $login); @@ -426,11 +428,14 @@ sub delete_user { my $form = $main::form; my $dbh = $self->dbconnect(); + + $dbh->begin_work; + my $query = qq|SELECT id FROM auth."user" WHERE login = ?|; my ($id) = selectrow_query($form, $dbh, $query, $login); - return $main::lxdebug->leave_sub() if (!$id); + $dbh->rollback and return $main::lxdebug->leave_sub() if (!$id); do_query($form, $dbh, qq|DELETE FROM auth.user_group WHERE user_id = ?|, $id); do_query($form, $dbh, qq|DELETE FROM auth.user_config WHERE user_id = ?|, $id); @@ -482,7 +487,10 @@ sub restore_session { while (my $ref = $sth->fetchrow_hashref()) { $self->{SESSION}->{$ref->{sess_key}} = $ref->{sess_value}; - $form->{$ref->{sess_key}} = $self->_load_value($ref->{sess_value}) if (!defined $form->{$ref->{sess_key}}); + next if defined $form->{$ref->{sess_key}}; + + my $params = $self->_load_value($ref->{sess_value}); + $form->{$ref->{sess_key}} = $params->{data} if $params->{auto_restore} || $params->{simple}; } $sth->finish(); @@ -493,15 +501,26 @@ sub restore_session { } sub _load_value { - return $_[1] if $_[1] !~ m/^---/; + my ($self, $value) = @_; + + return { simple => 1, data => $value } if $value !~ m/^---/; - my $value; + my %params = ( simple => 1 ); eval { - $value = YAML::Load($_[1]); + my $data = YAML::Load($value); + + if (ref $data eq 'HASH') { + map { $params{$_} = $data->{$_} } keys %{ $data }; + $params{simple} = 0; + + } else { + $params{data} = $data; + } + 1; - } or return $_[1]; + } or $params{data} = $value; - return $value; + return \%params; } sub destroy_session { @@ -512,6 +531,8 @@ sub destroy_session { if ($session_id) { my $dbh = $self->dbconnect(); + $dbh->begin_work; + do_query($main::form, $dbh, qq|DELETE FROM auth.session_content WHERE session_id = ?|, $session_id); do_query($main::form, $dbh, qq|DELETE FROM auth.session WHERE id = ?|, $session_id); @@ -530,6 +551,9 @@ sub expire_sessions { my $self = shift; my $dbh = $self->dbconnect(); + + $dbh->begin_work; + my $query = qq|DELETE FROM auth.session_content WHERE session_id IN @@ -575,6 +599,9 @@ sub create_or_refresh_session { $form = $main::form; $dbh = $self->dbconnect(); + $dbh->begin_work; + do_query($::form, $dbh, qq|LOCK auth.session_content|); + $query = qq|SELECT id FROM auth.session WHERE id = ?|; ($id) = selectrow_query($form, $dbh, $query, $session_id); @@ -598,8 +625,13 @@ sub save_session { my $self = shift; my $provided_dbh = shift; - my $dbh = $provided_dbh || $self->dbconnect(); + my $dbh = $provided_dbh || $self->dbconnect(1); + + return unless $dbh; + + $dbh->begin_work unless $provided_dbh; + do_query($::form, $dbh, qq|LOCK auth.session_content|); do_query($::form, $dbh, qq|DELETE FROM auth.session_content WHERE session_id = ?|, $session_id); if (%{ $self->{SESSION} }) { @@ -625,7 +657,7 @@ sub set_session_value { $self->{SESSION} ||= { }; while (my ($key, $value) = each %params) { - $self->{SESSION}->{ $key } = YAML::Dump($value); + $self->{SESSION}->{ $key } = YAML::Dump(ref($value) eq 'HASH' ? { data => $value } : $value); } $main::lxdebug->leave_sub(); @@ -649,12 +681,85 @@ sub delete_session_value { sub get_session_value { $main::lxdebug->enter_sub(); - my $self = shift; - my $value = $self->{SESSION} ? $self->_load_value($self->{SESSION}->{ $_[0] }) : undef; + my $self = shift; + my $params = $self->{SESSION} ? $self->_load_value($self->{SESSION}->{ $_[0] }) : {}; $main::lxdebug->leave_sub(); - return $value; + return $params->{data}; +} + +sub create_unique_sesion_value { + my ($self, $value, %params) = @_; + + $self->{SESSION} ||= { }; + + my @now = gettimeofday(); + my $key = "$$-" . ($now[0] * 1000000 + $now[1]) . "-"; + $self->{unique_counter} ||= 0; + + $self->{unique_counter}++ while exists $self->{SESSION}->{$key . $self->{unique_counter}}; + $self->{unique_counter}++; + + $value = { expiration => $params{expiration} ? ($now[0] + $params{expiration}) * 1000000 + $now[1] : undef, + no_auto => !$params{auto_restore}, + data => $value, + }; + + $self->{SESSION}->{$key . $self->{unique_counter}} = YAML::Dump($value); + + return $key . $self->{unique_counter}; +} + +sub save_form_in_session { + my ($self, %params) = @_; + + my $form = delete($params{form}) || $::form; + my $non_scalars = delete $params{non_scalars}; + my $data = {}; + + my %skip_keys = map { ( $_ => 1 ) } (qw(login password stylesheet version titlebar), @{ $params{skip_keys} || [] }); + + foreach my $key (grep { !$skip_keys{$_} } keys %{ $form }) { + $data->{$key} = $form->{$key} if !ref($form->{$key}) || $non_scalars; + } + + return $self->create_unique_sesion_value($data, %params); +} + +sub restore_form_from_session { + my ($self, $key, %params) = @_; + + my $data = $self->get_session_value($key); + return $self unless $data; + + my $form = delete($params{form}) || $::form; + my $clobber = exists $params{clobber} ? $params{clobber} : 1; + + map { $form->{$_} = $data->{$_} if $clobber || !exists $form->{$_} } keys %{ $data }; + + return $self; +} + +sub expire_session_keys { + my ($self) = @_; + + $self->{SESSION} ||= { }; + + my @now = gettimeofday(); + my $now = $now[0] * 1000000 + $now[1]; + + $self->delete_session_value(map { $_->[0] } + grep { $_->[1]->{expiration} && ($now > $_->[1]->{expiration}) } + map { [ $_, $self->_load_value($self->{SESSION}->{$_}) ] } + keys %{ $self->{SESSION} }); + + return $self; +} + +sub _has_expiration { + my ($value) = @_; + return (ref $value eq 'HASH') && exists($value->{expiration}) && $value->{data}; } sub set_cookie_environment_variable { @@ -821,6 +926,8 @@ sub save_group { my $form = $main::form; my $dbh = $self->dbconnect(); + $dbh->begin_work; + my ($query, $sth, $row, $rights); if (!$group->{id}) { @@ -866,6 +973,7 @@ sub delete_group { my $form = $main::from; my $dbh = $self->dbconnect(); + $dbh->begin_work; do_query($form, $dbh, qq|DELETE FROM auth.user_group WHERE group_id = ?|, $id); do_query($form, $dbh, qq|DELETE FROM auth.group_rights WHERE group_id = ?|, $id); @@ -1046,3 +1154,93 @@ sub load_rights_for_user { } 1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::Auth - Authentication and session handling + +=head1 FUNCTIONS + +=over 4 + +=item C + +Store all key/value pairs in C<%values> in the session. All of these +values are copied back into C<$::form> in the next request +automatically. + +The values can be any Perl structure. They are stored as YAML dumps. + +=item C + +Retrieve a value from the session. Returns C if the value +doesn't exist. + +=item C + +Create a unique key in the session and store C<$value> +there. + +If C<$params{expiration}> is set then it is interpreted as a number of +seconds after which the value is removed from the session. It will +never expire if that parameter is falsish. + +If C<$params{auto_restore}> is trueish then the value will be copied +into C<$::form> upon the next request automatically. It defaults to +C and has therefore different behaviour than +L. + +Returns the key created in the session. + +=item C + +Removes all keys from the session that have an expiration time set and +whose expiration time is in the past. + +=item C + +Stores the session values in the database. This is the only function +that actually stores stuff in the database. Neither the various +setters nor the deleter access the database. + +=item + +Stores the content of C<$params{form}> (default: C<$::form>) in the +session using L. + +If C<$params{non_scalars}> is trueish then non-scalar values will be +stored as well. Default is to only store scalar values. + +The following keys will never be saved: C, C, +C, C, C. Additional keys not to save +can be given as an array ref in C<$params{skip_keys}>. + +Returns the unique key under which the form is stored. + +=item + +Restores the form from the session into C<$params{form}> (default: +C<$::form>). + +If C<$params{clobber}> is falsish then existing values with the same +key in C<$params{form}> will not be overwritten. C<$params{clobber}> +is on by default. + +Returns C<$self>. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/Auth/Constants.pm b/SL/Auth/Constants.pm index 852271338..5a44dc1e3 100644 --- a/SL/Auth/Constants.pm +++ b/SL/Auth/Constants.pm @@ -11,6 +11,7 @@ our %EXPORT_TAGS = ( ERR => [ qw( ERR_PASSWORD ERR_BACKEND + ERR_USER ) ], SESSION => [ qw( SESSION_OK @@ -30,6 +31,7 @@ Exporter::export_ok_tags('all'); use constant OK => 0; use constant ERR_PASSWORD => 1; +use constant ERR_USER => 2; use constant ERR_BACKEND => 100; use constant SESSION_OK => 0; diff --git a/SL/Auth/DB.pm b/SL/Auth/DB.pm index 2ad131a8d..0168896f9 100644 --- a/SL/Auth/DB.pm +++ b/SL/Auth/DB.pm @@ -1,10 +1,12 @@ package SL::Auth::DB; +use strict; + +use Carp; + use SL::Auth::Constants qw(:all); use SL::DBUtils; -use strict; - sub new { $main::lxdebug->enter_sub(); @@ -26,7 +28,6 @@ sub authenticate { my $self = shift; my $login = shift; my $password = shift; - my $is_crypted = shift; my $dbh = $self->{auth}->dbconnect(); @@ -38,8 +39,13 @@ sub authenticate { my $query = qq|SELECT password FROM auth."user" WHERE login = ?|; my ($stored_password) = $dbh->selectrow_array($query, undef, $login); - $password = crypt $password, substr($login, 0, 2) if (!$password || !$is_crypted); - $stored_password = crypt $stored_password, substr($login, 0, 2) if (!$stored_password); + my ($algorithm, $algorithm2); + + # Empty password hashes in the database mean just that -- empty + # passwords. Hash it for easier comparison. + $stored_password = $self->hash_password(password => $stored_password) unless $stored_password; + ($algorithm, $stored_password) = $self->parse_password_entry($stored_password); + ($algorithm2, $password) = $self->parse_password_entry($self->hash_password(password => $password, algorithm => $algorithm, login => $login)); $main::lxdebug->leave_sub(); @@ -65,7 +71,7 @@ sub change_password { return ERR_BACKEND; } - $password = crypt $password, substr($login, 0, 2) if (!$is_crypted); + $password = $self->hash_password(password => $password) unless $is_crypted; do_query($main::form, $dbh, qq|UPDATE auth."user" SET password = ? WHERE login = ?|, $password, $login); @@ -80,4 +86,42 @@ sub verify_config { return 1; } +sub hash_password { + my ($self, %params) = @_; + + if (!$params{algorithm}) { + $params{algorithm} = 'SHA1'; + $params{fallback_algorithm} = 'MD5'; + } + + if ($params{algorithm} eq 'SHA1') { + if (eval { require Digest::SHA1; 1 }) { + return '{SHA1}' . Digest::SHA1::sha1_hex($params{password}); + + } elsif ($params{fallback_algorithm}) { + return $self->hash_password(%params, algorithm => $params{fallback_algorithm}); + + } else { + die 'Digest::SHA1 not available'; + } + + } elsif ($params{algorithm} eq 'MD5') { + require Digest::MD5; + return '{MD5}' . Digest::MD5::md5_hex($params{password}); + + } elsif ($params{algorithm} eq 'CRYPT') { + return '{CRYPT}' . crypt($params{password}, substr($params{login}, 0, 2)); + + } else { + croak 'Unsupported hash algorithm ' . $params{algorithm}; + } +} + +sub parse_password_entry { + my ($self, $password) = @_; + + return ($1, $2) if $password =~ m/^\{ ([^\}]+) \} (.+)/x; + return ('CRYPT', $password); +} + 1; diff --git a/SL/Controller/Base.pm b/SL/Controller/Base.pm index fff11ca3a..d80fca16d 100644 --- a/SL/Controller/Base.pm +++ b/SL/Controller/Base.pm @@ -65,6 +65,7 @@ sub render { my %params = ( %locals, AUTH => $::auth, + FLASH => $::form->{FLASH}, FORM => $::form, LOCALE => $::locale, LXCONFIG => \%::lx_office_conf, diff --git a/SL/DB.pm b/SL/DB.pm index f90a9c637..67888ef59 100644 --- a/SL/DB.pm +++ b/SL/DB.pm @@ -65,7 +65,7 @@ sub _register_db { } elsif ($type eq 'LXOFFICE_AUTH') { %connect_settings = ( driver => $::myconfig{dbdriver} || 'Pg', database => $::auth->{DB_config}->{db}, - host => $::auth->{DB_config}->{host}, + host => $::auth->{DB_config}->{host} || 'localhost', port => $::auth->{DB_config}->{port} || 5432, username => $::auth->{DB_config}->{user}, password => $::auth->{DB_config}->{password}, @@ -79,7 +79,7 @@ sub _register_db { %connect_settings = ( driver => $::myconfig{dbdriver} || 'Pg', database => $::myconfig{dbname}, - host => $::myconfig{dbhost}, + host => $::myconfig{dbhost} || 'localhost', port => $::myconfig{dbport} || 5432, username => $::myconfig{dbuser}, password => $::myconfig{dbpasswd}, diff --git a/SL/DB/Buchungsgruppe.pm b/SL/DB/Buchungsgruppe.pm index 26f446b33..5a486796d 100644 --- a/SL/DB/Buchungsgruppe.pm +++ b/SL/DB/Buchungsgruppe.pm @@ -1,14 +1,9 @@ -# This file has been auto-generated only because it didn't exist. -# Feel free to modify it at will; it will not be overwritten automatically. - package SL::DB::Buchungsgruppe; use strict; use SL::DB::MetaSetup::Buchungsgruppe; - -# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all. -__PACKAGE__->meta->make_manager_class; +use SL::DB::Manager::Buchungsgruppe; sub income_accno_id { my ($self, $taxzone) = @_; diff --git a/SL/DB/Manager/Buchungsgruppe.pm b/SL/DB/Manager/Buchungsgruppe.pm new file mode 100644 index 000000000..068ef6b32 --- /dev/null +++ b/SL/DB/Manager/Buchungsgruppe.pm @@ -0,0 +1,21 @@ +package SL::DB::Manager::Buchungsgruppe; + +use strict; + +use SL::DB::Helper::Manager; +use base qw(SL::DB::Helper::Manager); + +use SL::DB::Helper::Sorted; + +sub object_class { 'SL::DB::Buchungsgruppe' } + +__PACKAGE__->make_manager_methods; + +sub _sort_spec { + return ( default => [ 'sortkey', 1 ], + columns => { SIMPLE => 'ALL', + description => 'lower(description)', + }); +} + +1; diff --git a/SL/Dispatcher.pm b/SL/Dispatcher.pm index f22cf0e9f..6512f0312 100644 --- a/SL/Dispatcher.pm +++ b/SL/Dispatcher.pm @@ -35,6 +35,11 @@ sub new { return $self; } +sub interface_type { + my ($self) = @_; + return $self->{interface} eq 'cgi' ? 'CGI' : 'FastCGI'; +} + sub pre_request_checks { if (!$::auth->session_tables_present) { if ($::form->{script} eq 'admin.pl') { @@ -193,11 +198,11 @@ sub handle_request { $::locale = Locale->new($::myconfig{countrycode}); - show_error('login/password_error', 'password') if SL::Auth::OK != $::auth->authenticate($::form->{login}, $::form->{password}, 0); + show_error('login/password_error', 'password') if SL::Auth::OK != $::auth->authenticate($::form->{login}, $::form->{password}); $::auth->set_session_value('login', $::form->{login}, 'password', $::form->{password}); $::auth->create_or_refresh_session; - $::auth->delete_session_value('FLASH')->save_session(); + $::auth->delete_session_value('FLASH'); delete $::form->{password}; if ($action) { @@ -227,7 +232,9 @@ sub handle_request { $::locale = undef; $::form = undef; $::myconfig = (); - Form::disconnect_standard_dbh unless $self->_interface_is_fcgi; + Form::disconnect_standard_dbh; + $::auth->expire_session_keys->save_session; + $::auth->dbdisconnect; $::lxdebug->end_request; $::lxdebug->leave_sub; diff --git a/SL/Form.pm b/SL/Form.pm index 6e7145f20..23dd5be50 100644 --- a/SL/Form.pm +++ b/SL/Form.pm @@ -133,6 +133,7 @@ sub _request_to_hash { my $self = shift; my $input = shift; + my $uploads = {}; if (!$ENV{'CONTENT_TYPE'} || ($ENV{'CONTENT_TYPE'} !~ /multipart\/form-data\s*;\s*boundary\s*=\s*(.+)$/)) { @@ -140,7 +141,7 @@ sub _request_to_hash { $self->_input_to_hash($input); $main::lxdebug->leave_sub(2); - return; + return $uploads; } my ($name, $filename, $headers_done, $content_type, $boundary_found, $need_cr, $previous); @@ -185,7 +186,7 @@ sub _request_to_hash { substr $line, $-[0], $+[0] - $-[0], ""; } - $previous = $self->_store_value($name, '') if ($name); + $previous = _store_value($uploads, $name, '') if ($name); $self->{FILENAME} = $filename if ($filename); next; @@ -206,6 +207,8 @@ sub _request_to_hash { ${ $previous } =~ s|\r?\n$|| if $previous; $main::lxdebug->leave_sub(2); + + return $uploads; } sub _recode_recursively { @@ -256,10 +259,11 @@ sub new { $self->_input_to_hash($ENV{QUERY_STRING}) if $ENV{QUERY_STRING}; $self->_input_to_hash($ARGV[0]) if @ARGV && $ARGV[0]; + my $uploads; if ($ENV{CONTENT_LENGTH}) { my $content; read STDIN, $content, $ENV{CONTENT_LENGTH}; - $self->_request_to_hash($content); + $uploads = $self->_request_to_hash($content); } my $db_charset = $::lx_office_conf{system}->{dbcharset}; @@ -270,6 +274,8 @@ sub new { _recode_recursively(SL::Iconv->new($encoding, $db_charset), $self); + map { $self->{$_} = $uploads->{$_} } keys %{ $uploads } if $uploads; + #$self->{version} = "2.6.1"; # Old hardcoded but secure style open VERSION_FILE, "VERSION"; # New but flexible code reads version from VERSION-file $self->{version} = ; @@ -809,7 +815,7 @@ sub _prepare_html_template { $additional_params->{"conf_latex_templates"} = $::lx_office_conf{print_templates}->{latex}; $additional_params->{"conf_opendocument_templates"} = $::lx_office_conf{print_templates}->{opendocument}; $additional_params->{"conf_vertreter"} = $::lx_office_conf{system}->{vertreter}; - $additional_params->{"conf_show_best_before"} = $::lx_office_conf{system}->{show_best_before}; + $additional_params->{"conf_show_best_before"} = $::lx_office_conf{features}->{show_best_before}; $additional_params->{"conf_parts_image_css"} = $::lx_office_conf{features}->{parts_image_css}; $additional_params->{"conf_parts_listing_images"} = $::lx_office_conf{features}->{parts_listing_images}; $additional_params->{"conf_parts_show_image"} = $::lx_office_conf{features}->{parts_show_image}; diff --git a/SL/Helper/Flash.pm b/SL/Helper/Flash.pm index 8f68d00c7..876de9644 100644 --- a/SL/Helper/Flash.pm +++ b/SL/Helper/Flash.pm @@ -16,7 +16,7 @@ sub flash { } sub flash_later { - $::auth->set_session_value(FLASH => _store_flash($::auth->get_session_value('FLASH'), @_))->save_session(); + $::auth->set_session_value(FLASH => _store_flash($::auth->get_session_value('FLASH'), @_)); } sub render_flash { diff --git a/SL/Template/Plugin/L.pm b/SL/Template/Plugin/L.pm index 9995722e1..513f4a221 100644 --- a/SL/Template/Plugin/L.pm +++ b/SL/Template/Plugin/L.pm @@ -207,7 +207,7 @@ sub options_for_select { my $value_title_sub = $options{value_title_sub}; - my %selected = map { ( $_ => 1 ) } @{ ref($options{default}) eq 'ARRAY' ? $options{default} : $options{default} ? [ $options{default} ] : [] }; + my %selected = map { ( $_ => 1 ) } @{ ref($options{default}) eq 'ARRAY' ? $options{default} : defined($options{default}) ? [ $options{default} ] : [] }; my $access = sub { my ($element, $index, $key, $sub) = @_; @@ -231,7 +231,7 @@ sub options_for_select { my $code = ''; foreach my $result (@elements) { my %attributes = ( value => $result->[0] ); - $attributes{selected} = 'selected' if $selected{ $result->[0] || '' }; + $attributes{selected} = 'selected' if $selected{ defined($result->[0]) ? $result->[0] : '' }; $code .= $self->html_tag('option', _H($result->[1]), %attributes); } diff --git a/bin/mozilla/admin.pl b/bin/mozilla/admin.pl index b89487c7e..ddb12b1d8 100755 --- a/bin/mozilla/admin.pl +++ b/bin/mozilla/admin.pl @@ -34,6 +34,7 @@ use DBI; use CGI; +use Encode; use English qw(-no_match_vars); use Fcntl; use File::Copy; @@ -78,7 +79,7 @@ sub run { $form->{favicon} = "favicon.ico"; if ($form->{action}) { - if ($auth->authenticate_root($form->{rpw}, 0) != $auth->OK()) { + if ($auth->authenticate_root($form->{rpw}) != $auth->OK()) { $form->{error_message} = $locale->text('Incorrect Password!'); adminlogin(); } else { @@ -342,7 +343,10 @@ sub list_users { delete $members{"root login"}; - map { $_->{templates} =~ s|.*/||; } values %members; + for (values %members) { + $_->{templates} =~ s|.*/||; + $_->{login_url} = $::locale->is_utf8 ? Encode::encode('utf-8-strict', $_->{login}) : $_->{login_url}; + } $form->{title} = "Lx-Office ERP " . $locale->text('Administration'); $form->{LOCKED} = -e _nologin_file_name(); diff --git a/bin/mozilla/do.pl b/bin/mozilla/do.pl index d6e594f5b..2bd7f6b42 100644 --- a/bin/mozilla/do.pl +++ b/bin/mozilla/do.pl @@ -1361,7 +1361,7 @@ sub transfer_out { my $pinfo = $part_info_map{$request->{parts_id}}; my $binfo = $bin_info_map{$request->{bin_id}}; - if ($::lx_office_conf{system}->{show_best_before}) { + if ($::lx_office_conf{features}->{show_best_before}) { push @{ $form->{ERRORS} }, $locale->text("There is not enough available of '#1' at warehouse '#2', bin '#3', #4, #5, for the transfer of #6.", $pinfo->{description}, $binfo->{warehouse_description}, diff --git a/bin/mozilla/drafts.pl b/bin/mozilla/drafts.pl index f6cc7b6d0..c471d009b 100644 --- a/bin/mozilla/drafts.pl +++ b/bin/mozilla/drafts.pl @@ -129,7 +129,10 @@ sub load_draft { $form->{draft_description} = $description; $form->{remove_draft} = 'checked'; } - + # Ich vergesse bei Rechnungsentwürfe das Rechnungsdatum zu ändern. Dadurch entstehen + # ungültige Belege. Vielleicht geht es anderen ähnlich jan 19.2.2011 + $form->{invdate} = $form->current_date(\%myconfig); # Aktuelles Rechnungsdatum ... + $form->{duedate} = $form->current_date(\%myconfig); # Aktuelles Fälligkeitsdatum ... update(); $main::lxdebug->leave_sub(); diff --git a/bin/mozilla/ic.pl b/bin/mozilla/ic.pl index b5588be3b..4eb1e41e1 100644 --- a/bin/mozilla/ic.pl +++ b/bin/mozilla/ic.pl @@ -1759,7 +1759,7 @@ sub save { $auth->assert('part_service_assembly_edit'); - my ($parts_id, %newform, $previousform, $amount, $callback); + my ($parts_id, %newform, $amount, $callback); # check if there is a part number - commented out, cause there is an automatic allocation of numbers # $form->isblank("partnumber", $locale->text(ucfirst $form->{item}." Part Number missing!")); @@ -1800,20 +1800,14 @@ sub save { # save the new form variables before splitting previousform map { $newform{$_} = $form->{$_} } keys %$form; - $previousform = $form->unescape($form->{previousform}); - # don't trample on previous variables map { delete $form->{$_} } keys %newform; my $ic_cvar_configs = CVar->get_configs(module => 'IC'); my @ic_cvar_fields = map { "cvar_$_->{name}" } @{ $ic_cvar_configs }; - # now take it apart and restore original values - foreach my $item (split /&/, $previousform) { - my ($key, $value) = split m/=/, $item, 2; - $value =~ s/%26/&/g; - $form->{$key} = $value; - } + # restore original values + $::auth->restore_form_from_session($newform{previousform}, form => $form); $form->{taxaccounts} = $newform{taxaccount2}; if ($form->{item} eq 'assembly') { diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl index af69e4488..be7062ad2 100644 --- a/bin/mozilla/io.pl +++ b/bin/mozilla/io.pl @@ -703,11 +703,11 @@ sub new_item { $form->{old_callback} = $form->escape($form->{callback}, 1); $form->{callback} = $form->escape("$form->{script}?action=display_form", 1); - # save all form variables except action in a previousform variable - my $previousform = join '&', map { my $value = $form->{$_}; $value =~ s/&/%26/; "$_=$value" } grep { !/action/ } keys %$form; + # save all form variables except action in the session and keep the key in the previousform variable + my $previousform = $::auth->save_form_in_session(skip_keys => [ qw(action) ]); my @HIDDENS; - push @HIDDENS, { 'name' => 'previousform', 'value' => $form->escape($previousform, 1) }; + push @HIDDENS, { 'name' => 'previousform', 'value' => $previousform }; push @HIDDENS, map +{ 'name' => $_, 'value' => $form->{$_} }, qw(rowcount vc); push @HIDDENS, map +{ 'name' => $_, 'value' => $form->{"${_}_$form->{rowcount}"} }, qw(partnumber description unit); push @HIDDENS, { 'name' => 'taxaccount2', 'value' => $form->{taxaccounts} }; diff --git a/bin/mozilla/licenses.pl b/bin/mozilla/licenses.pl index 5aee28b5d..fb065f254 100644 --- a/bin/mozilla/licenses.pl +++ b/bin/mozilla/licenses.pl @@ -325,7 +325,7 @@ sub add { $form->{title} = $locale->text('Add License'); - if (!$::lx_office_conf{system}->{lizenzen}) { + if (!$::lx_office_conf{features}->{lizenzen}) { $form->error( $locale->text( 'The licensing module has been deactivated in the configuration.') @@ -518,7 +518,7 @@ sub search { $form->{title} = $locale->text('Licenses'); - if (!$::lx_office_conf{system}->{lizenzen}) { + if (!$::lx_office_conf{features}->{lizenzen}) { $form->error( $locale->text( 'The licensing module has been deactivated in the configuration.') diff --git a/bin/mozilla/login.pl b/bin/mozilla/login.pl index 49cb6c613..03e6dd947 100644 --- a/bin/mozilla/login.pl +++ b/bin/mozilla/login.pl @@ -65,7 +65,7 @@ sub run { %::myconfig = $auth->read_user($form->{login}) if ($form->{login}); $::locale = Locale->new($::myconfig{countrycode}) if $::myconfig{countrycode}; - if (!$::myconfig{login} || (SL::Auth::OK != $auth->authenticate($form->{login}, $form->{password}, 0))) { + if (SL::Auth::OK != $auth->authenticate($::myconfig{login}, $form->{password})) { $form->{error_message} = $::locale->text('Incorrect username or password!'); login_screen(); } else { @@ -163,6 +163,7 @@ sub company_logo { $form->{stylesheet} = $myconfig{stylesheet}; $form->{title} = $::locale->text('Lx-Office'); + $form->{interface} = $::dispatcher->interface_type; # create the logo screen $form->header() unless $form->{noheader}; diff --git a/bin/mozilla/ustva.pl b/bin/mozilla/ustva.pl index f7874cdad..6466565b0 100644 --- a/bin/mozilla/ustva.pl +++ b/bin/mozilla/ustva.pl @@ -116,8 +116,7 @@ sub report { my $company_given = ($form->{company} ne '') ? qq|

$form->{company}

\n| - : qq|| + : qq|| . $locale->text('No Company Name given') . qq|!
|; diff --git a/bin/mozilla/wh.pl b/bin/mozilla/wh.pl index f49710785..2b49ba00c 100644 --- a/bin/mozilla/wh.pl +++ b/bin/mozilla/wh.pl @@ -438,7 +438,7 @@ sub create_assembly { $form->error($locale->text('The warehouse or the bin is missing.')); } - if (!$::lx_office_conf{system}->{show_best_before}) { + if (!$::lx_office_conf{features}->{show_best_before}) { $form->{bestbefore} = ''; } diff --git a/config/lx_office.conf.default b/config/lx_office.conf.default index b4d4471f7..1972e9530 100644 --- a/config/lx_office.conf.default +++ b/config/lx_office.conf.default @@ -58,7 +58,7 @@ bind_password = [system] # EUR: Einnahmen-Überschussrechnung (net income method). Set this to 1 -# if your company uses the net income method and to 0 for balacing. +# if your company uses the net income method and to 0 for balancing. eur = 1 # Set language for login and admin forms. Currently "de" (German), diff --git a/controller.pl b/controller.pl new file mode 120000 index 000000000..385000d1b --- /dev/null +++ b/controller.pl @@ -0,0 +1 @@ +am.pl \ No newline at end of file diff --git a/css/lx-office-erp.css b/css/lx-office-erp.css index 8151719df..6f25ee507 100644 --- a/css/lx-office-erp.css +++ b/css/lx-office-erp.css @@ -121,6 +121,15 @@ body.menu { border-style:solid; border-width:thin; } +.message_error_label { + font-size: 0.8em; + padding:5px; + background-color: #FEE; + font-weight:normal; + text-align:left; + border-style:solid; + border-width:thin; +} /* Überschriftsbalken diff --git a/doc/INSTALL.fcgi b/doc/INSTALL.fcgi index 186ca33cb..454be0396 100644 --- a/doc/INSTALL.fcgi +++ b/doc/INSTALL.fcgi @@ -127,7 +127,7 @@ werden aber umgeleitet: # Zugriff über cgi Alias /web/path/to/lx-office-erp /path/to/lx-office-erp - # Zugriff mit mod_fastcgi: + # Zugriff mit mod_fcgid: AliasMatch ^/web/path/to/lx-office-erp-fcgid/[^/]+\.pl /path/to/lx-office-erp/dispatcher.fcgi Alias /web/path/to/lx-office-erp-fcgid/ /path/to/lx-office-erp/ @@ -136,8 +136,8 @@ werden aber umgeleitet: Alias /web/path/to/lx-office-erp-fastcgi/ /path/to/lx-office-erp/ Dann ist unter C die normale Version erreichbar, -und unter C bzw. -C die FastCGI Version. +und unter C bzw. +C die FastCGI Version. Achtung: @@ -148,7 +148,7 @@ vhost. =head2 Entwicklungsaspekte Wenn Änderungen in der Konfiguration von Lx-Office gemacht werden, muss der -Server neu gestartet werden. +Webserver neu gestartet werden. Bei der Entwicklung für FastCGI ist auf ein paar Fallstricke zu achten. Dadurch dass das Programm in einer Endlosschleife läuft, müssen folgende Aspekte @@ -180,7 +180,7 @@ In C gibt es einen sauber abgetrennten Block der alle kanonischen globalen Variablen listet und erklärt. Bitte keine anderen einführen ohne das sauber zu dokumentieren. -Datenbankverbindungen wird noch ein Guide verfasst werden, wie man sichergeht, +Datenbankverbindungen wird noch ein Guide verfasst werden, wie man sicher geht, dass man die richtige erwischt. =head2 Performance und Statistiken diff --git a/doc/changelog b/doc/changelog index 0311afec7..520aa2774 100644 --- a/doc/changelog +++ b/doc/changelog @@ -2,6 +2,16 @@ # Veränderungen von Lx-Office ERP # ################################### + ab Feb 2011 Release 2.7-unstable + + + + Kleinere neue Features und Detailverbesserungen: + + - Beim Laden von Rechnungsentwürfen, das Fälligkeits- und Rechnungsdatum duch + das Tagesdatum ersetzen + + 2011-02-02 - Release 2.6.2 Größere neue Features: diff --git a/doc/dokumentenvorlagen-und-variablen.html b/doc/dokumentenvorlagen-und-variablen.html index d456541ff..24df1142d 100644 --- a/doc/dokumentenvorlagen-und-variablen.html +++ b/doc/dokumentenvorlagen-und-variablen.html @@ -874,6 +874,10 @@ td { serialnumber Seriennummer + + tax_rate + Steuersatz + transdate_oe Auftragsdatum des Originalauftrags, wenn die Rechnung aus einem Sammelauftrag erstellt wurde diff --git a/locale/de/all b/locale/de/all index 41038e16e..dd550435e 100644 --- a/locale/de/all +++ b/locale/de/all @@ -1897,6 +1897,7 @@ $self->{texts} = { 'Warning' => 'Warnung', 'Warnings during template upgrade' => 'Warnungen bei Aktualisierung der Dokumentenvorlagen', 'WebDAV link' => 'WebDAV-Link', + 'Webserver interface' => 'Webserverschnittstelle', 'Weight' => 'Gewicht', 'Weight unit' => 'Gewichtseinheit', 'What term you are looking for?' => 'Nach welchem Begriff wollen Sie suchen?', diff --git a/locale/de_DE/all b/locale/de_DE/all index 9d1902acd..3220d0485 100644 --- a/locale/de_DE/all +++ b/locale/de_DE/all @@ -1897,6 +1897,7 @@ $self->{texts} = { 'Warning' => 'Warnung', 'Warnings during template upgrade' => 'Warnungen bei Aktualisierung der Dokumentenvorlagen', 'WebDAV link' => 'WebDAV-Link', + 'Webserver interface' => 'Webserver nutzt', 'Weight' => 'Gewicht', 'Weight unit' => 'Gewichtseinheit', 'What term you are looking for?' => 'Nach welchem Begriff wollen Sie suchen?', diff --git a/locale/en/all b/locale/en/all index cddc3d0cd..0253d49a0 100644 --- a/locale/en/all +++ b/locale/en/all @@ -1896,6 +1896,7 @@ $self->{texts} = { 'Warning' => '', 'Warnings during template upgrade' => '', 'WebDAV link' => '', + 'Webserver interface' => '', 'Weight' => '', 'Weight unit' => '', 'What term you are looking for?' => '', diff --git a/templates/webpages/admin/list_users.html b/templates/webpages/admin/list_users.html index 0828b00c3..eb55dc51c 100644 --- a/templates/webpages/admin/list_users.html +++ b/templates/webpages/admin/list_users.html @@ -21,7 +21,7 @@ [% FOREACH row = MEMBERS %] -  [% HTML.escape(row.login) %] +  [% HTML.escape(row.login) %]  [% HTML.escape(row.name) %]  [% HTML.escape(row.company) %]  [% HTML.escape(row.templates) %] diff --git a/templates/webpages/generic/error.html b/templates/webpages/generic/error.html index cb3f22531..7778152b6 100644 --- a/templates/webpages/generic/error.html +++ b/templates/webpages/generic/error.html @@ -2,7 +2,7 @@ [% USE HTML %]
[% IF title_error %][% title_error %][% ELSE %][% 'Error!' | $T8 %][% END %] -

[% label_error %]

+

[% label_error %]

@@ -10,7 +10,7 @@ [%- IF SHOW_BACK_BUTTON %]

- diff --git a/templates/webpages/login/company_logo.html b/templates/webpages/login/company_logo.html index 7946c5274..10adcc0aa 100644 --- a/templates/webpages/login/company_logo.html +++ b/templates/webpages/login/company_logo.html @@ -25,11 +25,11 @@ - + - + @@ -40,6 +40,10 @@ + + + +
[% 'User' | $T8 %][% 'User' | $T8 %] [% HTML.escape(myconfig_name) %]
[% 'Language' | $T8 %][% 'Language' | $T8 %] [% HTML.escape(myconfig_countrycode) %]
[% 'Database Host' | $T8 %] [% HTML.escape(myconfig_dbhost) %]
[% 'Webserver interface' | $T8 %][% HTML.escape(interface) %]
[% 'Lx-Office Homepage' | $T8 %]: http://lx-office.org