From: Sven Schöling Date: Wed, 8 Aug 2012 15:48:29 +0000 (+0200) Subject: Merge branch 'master' of vc.linet-services.de:public/lx-office-erp X-Git-Tag: release-3.0.0beta1~297^2~17 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/4ab897fdb1a54cd753ec66ebc8fbd5ffdd883cd6?hp=804893ae520f82feba9a736d7d1a857699b48acf Merge branch 'master' of vc.linet-services.de:public/lx-office-erp --- diff --git a/SL/Request.pm b/SL/Request.pm index 64662875d..a8ae4c137 100644 --- a/SL/Request.pm +++ b/SL/Request.pm @@ -53,6 +53,10 @@ sub _input_to_hash { sub _parse_multipart_formdata { my ($target, $temp_target, $input) = @_; my ($name, $filename, $headers_done, $content_type, $boundary_found, $need_cr, $previous, $p_attachment, $encoding, $transfer_encoding); + my $data_start = 0; + + # teach substr and length to use good ol' bytes, not 'em fancy characters + use bytes; # We SHOULD honor encodings and transfer-encodings here, but as hard as I # looked I couldn't find a reasonably recent webbrowser that makes use of @@ -63,12 +67,21 @@ sub _parse_multipart_formdata { $ENV{'CONTENT_TYPE'} =~ /multipart\/form-data\s*;\s*boundary\s*=\s*(.+)$/; my $boundary = '--' . $1; + my $index = 0; + my $line_length; foreach my $line (split m/\n/, $input) { - last if (($line eq "${boundary}--") || ($line eq "${boundary}--\r")); + $line_length = length $line; + + if ($line =~ /^\Q$boundary\E(--)?\r?$/) { + my $last_boundary = $1; + my $data = substr $input, $data_start, $index - $data_start; + $data =~ s/\r?\n$//; - if (($line eq $boundary) || ($line eq "$boundary\r")) { - ${ $previous } =~ s|\r?\n$|| if $previous; - ${ $previous } = Encode::decode($encoding, $$previous) if $previous && !$filename && !$transfer_encoding eq 'binary'; + if ($previous && !$filename && $transfer_encoding && $transfer_encoding ne 'binary') { + ${ $previous } = Encode::decode($encoding, $data); + } else { + ${ $previous } = $data; + } undef $previous; undef $filename; @@ -79,7 +92,7 @@ sub _parse_multipart_formdata { $need_cr = 0; $encoding = $::lx_office_conf{system}->{dbcharset} || Common::DEFAULT_CHARSET; $transfer_encoding = undef; - + last if $last_boundary; next; } @@ -90,6 +103,7 @@ sub _parse_multipart_formdata { if (!$line) { $headers_done = 1; + $data_start = $index + $line_length + 1; next; } @@ -159,11 +173,10 @@ sub _parse_multipart_formdata { next unless $previous; - ${ $previous } .= "${line}\n"; + } continue { + $index += $line_length + 1; } - ${ $previous } =~ s|\r?\n$|| if $previous; - $::lxdebug->leave_sub(2); } diff --git a/locale/de/all b/locale/de/all index 9f31c8c66..224cdfac5 100644 --- a/locale/de/all +++ b/locale/de/all @@ -846,6 +846,7 @@ $self->{texts} = { 'Filter for customer variables' => 'Filter für benutzerdefinierte Kundenvariablen', 'Filter for item variables' => 'Filter für benutzerdefinierte Artikelvariablen', 'Finish' => 'Abschließen', + 'First 20 Lines' => 'Nur erste 20 Datensätze', 'Fix transaction' => 'Buchung korrigieren', 'Fix transactions' => 'Buchungen korrigieren', 'Folgekonto' => 'Folgekonto', @@ -879,6 +880,7 @@ $self->{texts} = { 'From' => 'Von', 'From Date' => 'Von', 'Full Access' => 'Vollzugriff', + 'Full Preview' => 'Alles', 'Full access to all functions' => 'Vollzugriff auf alle Funktionen', 'Fwd' => 'Vorwärts', 'GL Transaction' => 'Dialogbuchung', @@ -908,7 +910,6 @@ $self->{texts} = { 'Hardcopy' => 'Seite drucken', 'Has serial number' => 'Hat eine Serienummer', 'Heading' => 'Überschrift', - 'Headings' => 'Überschriften', 'Help' => 'Hilfe', 'Help Template Variables' => 'Hilfe zu Dokumenten-Variablen', 'Help on column names' => 'Hilfe zu Spaltennamen', @@ -1270,6 +1271,7 @@ $self->{texts} = { 'On Hand' => 'Auf Lager', 'On Order' => 'Ist bestellt', 'One or more Perl modules missing' => 'Ein oder mehr Perl-Module fehlen', + 'Only Warnings and Errors' => 'Nur Warnungen und Fehler', 'Only due follow-ups' => 'Nur fällige Wiedervorlagen', 'Only shown in item mode' => 'werden nur im Artikelmodus angezeigt', 'Oops. No valid action found to dispatch. Please report this case to the Lx-Office team.' => 'Ups. Es wurde keine gültige Funktion zum Aufrufen gefunden. Bitte berichten Sie diesen Fall den Lx-Office-Entwicklern.', @@ -1404,6 +1406,7 @@ $self->{texts} = { 'Prepare bank transfer via SEPA XML' => 'Überweisung via SEPA XML vorbereiten', 'Prepayment' => 'Vorauszahlung', 'Preview' => 'Druckvorschau', + 'Preview Mode' => 'Vorschaumodus', 'Previous transdate text' => 'wurde gespeichert am', 'Previous transnumber text' => 'Letzte Buchung mit der Buchungsnummer', 'Price' => 'Preis', diff --git a/scripts/task_server.pl b/scripts/task_server.pl index f438b7410..8c17ca70a 100755 --- a/scripts/task_server.pl +++ b/scripts/task_server.pl @@ -27,6 +27,7 @@ use SL::DB::BackgroundJob; use SL::BackgroundJob::ALL; use SL::Form; use SL::Helper::DateTime; +use SL::InstanceConfiguration; use SL::LXDebug; use SL::LxOfficeConf; use SL::Locale; @@ -38,11 +39,12 @@ sub lxinit { package main; - $::lxdebug = LXDebug->new; - $::locale = Locale->new($::lx_office_conf{system}->{language}); - $::form = Form->new; - $::auth = SL::Auth->new; - $::request = { cgi => CGI->new({}) }; + $::lxdebug = LXDebug->new; + $::locale = Locale->new($::lx_office_conf{system}->{language}); + $::form = Form->new; + $::auth = SL::Auth->new; + $::instance_conf = SL::InstanceConfiguration->new; + $::request = { cgi => CGI->new({}) }; die 'cannot reach auth db' unless $::auth->session_tables_present; diff --git a/t/Support/TestSetup.pm b/t/Support/TestSetup.pm index 5b6e2bb1f..cb8fd7ffb 100644 --- a/t/Support/TestSetup.pm +++ b/t/Support/TestSetup.pm @@ -11,7 +11,6 @@ use SL::LXDebug; use Data::Dumper; use SL::LxOfficeConf; use SL::InstanceConfiguration; -SL::LxOfficeConf->read; sub _login { my $login = shift; @@ -45,6 +44,8 @@ sub _login { } sub login { + SL::LxOfficeConf->read; + my $login = shift || $::lx_office_conf{testing}{login} || 'demo'; _login($login); } diff --git a/t/request/post_multipart.t b/t/request/post_multipart.t new file mode 100644 index 000000000..767807b90 --- /dev/null +++ b/t/request/post_multipart.t @@ -0,0 +1,107 @@ +use strict; +use utf8; + +use lib 't'; +use lib 'modules/fallback'; +BEGIN { + unshift @INC, 'modules/override'; +} + +use Support::TestSetup; +use Test::More tests => 2; +use Data::Dumper; +require Test::Deep; +use Encode; + +use SL::Request; + +Support::TestSetup::login(); + +open my $fh, '<', 't/request/post_multipart_1' or die "can't load test"; +my $data = do { $/ = undef; <$fh> }; + +my $t = {}; +my $tt = {}; + +local $ENV{CONTENT_TYPE} = 'multipart/form-data; boundary=---------------------------23281168279961'; +SL::Request::_parse_multipart_formdata($t, $tt, $data); + + +my $blob = Encode::encode('utf-8', qq|\x{feff}Stunde;Montag;Dienstag;Mittwoch;Donnerstag;Freitag +1;Mathe;Deutsch;Englisch;Mathe;Kunst +2;Sport;Französisch;Geschichte;Sport;Geschichte +3;Sport;"Religion ev;kath";Kunst;;Kunst|); + +my $t_cmp = { + 'profile' => { + 'name' => undef, + 'type' => undef + }, + 'quote_char' => undef, + 'file' => $blob, + 'custom_sep_char' => undef, + 'sep_char' => undef, + 'settings' => { + 'article_number_policy' => undef, + 'sellprice_places' => undef, + 'charset' => undef, + 'apply_buchungsgruppe' => undef, + 'full_preview' => undef, + 'parts_type' => undef, + 'default_unit' => undef, + 'default_buchungsgruppe' => undef, + 'duplicates' => undef, + 'numberformat' => undef, + 'sellprice_adjustment_type' => undef, + 'shoparticle_if_missing' => undef, + 'sellprice_adjustment' => undef + }, + 'custom_escape_char' => undef, + 'action_test' => undef, + 'custom_quote_char' => undef, + 'escape_char' => undef, + 'action' => undef + }; +$t_cmp->{ATTACHMENTS}{file}{data} = \$t_cmp->{'file'}; + + +is_deeply $t, $t_cmp; + +is_deeply $tt, + { + 'profile' => { + 'name' => '', + 'type' =>'parts', + }, + 'file' => undef, + 'quote_char' => 'quote', + 'custom_sep_char' => '', + 'sep_char' => 'semicolon', + 'settings' => { + 'article_number_policy' => 'update_prices', + 'sellprice_places' => 2, + 'charset' => 'UTF-8', + 'apply_buchungsgruppe' => 'all', + 'full_preview' => '0', + 'parts_type' => 'part', + 'default_unit' => 'g', + 'default_buchungsgruppe' => '815', + 'duplicates' => 'no_check', + 'numberformat' => '1.000,00', + 'sellprice_adjustment_type' => 'percent', + 'shoparticle_if_missing' => '0', + 'sellprice_adjustment' =>'0' + }, + 'custom_escape_char' => '', + 'action_test' => 'Test und Vorschau', + 'ATTACHMENTS' => { + 'file' => { + 'filename' => 'from_wikipedia.csv' + } + }, + 'custom_quote_char' => '', + 'escape_char' => 'quote', + 'action' => 'CsvImport/dispatch', + 'FILENAME' => 'from_wikipedia.csv' + }; + diff --git a/t/request/post_multipart_1 b/t/request/post_multipart_1 new file mode 100644 index 000000000..c3ced0fc8 --- /dev/null +++ b/t/request/post_multipart_1 @@ -0,0 +1,101 @@ +-----------------------------23281168279961 +Content-Disposition: form-data; name="action" + +CsvImport/dispatch +-----------------------------23281168279961 +Content-Disposition: form-data; name="profile.type" + +parts +-----------------------------23281168279961 +Content-Disposition: form-data; name="profile.name" + + +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.numberformat" + +1.000,00 +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.charset" + +UTF-8 +-----------------------------23281168279961 +Content-Disposition: form-data; name="sep_char" + +semicolon +-----------------------------23281168279961 +Content-Disposition: form-data; name="custom_sep_char" + + +-----------------------------23281168279961 +Content-Disposition: form-data; name="quote_char" + +quote +-----------------------------23281168279961 +Content-Disposition: form-data; name="custom_quote_char" + + +-----------------------------23281168279961 +Content-Disposition: form-data; name="escape_char" + +quote +-----------------------------23281168279961 +Content-Disposition: form-data; name="custom_escape_char" + + +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.duplicates" + +no_check +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.article_number_policy" + +update_prices +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.sellprice_places" + +2 +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.sellprice_adjustment" + +0 +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.sellprice_adjustment_type" + +percent +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.shoparticle_if_missing" + +0 +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.parts_type" + +part +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.default_buchungsgruppe" + +815 +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.apply_buchungsgruppe" + +all +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.default_unit" + +g +-----------------------------23281168279961 +Content-Disposition: form-data; name="settings.full_preview" + +0 +-----------------------------23281168279961 +Content-Disposition: form-data; name="file"; filename="from_wikipedia.csv" +Content-Type: text/comma-separated-values + +Stunde;Montag;Dienstag;Mittwoch;Donnerstag;Freitag +1;Mathe;Deutsch;Englisch;Mathe;Kunst +2;Sport;Französisch;Geschichte;Sport;Geschichte +3;Sport;"Religion ev;kath";Kunst;;Kunst +-----------------------------23281168279961 +Content-Disposition: form-data; name="action_test" + +Test und Vorschau +-----------------------------23281168279961-- diff --git a/templates/webpages/csv_import/_preview.html b/templates/webpages/csv_import/_preview.html index fe088e25e..01fe4d9ff 100644 --- a/templates/webpages/csv_import/_preview.html +++ b/templates/webpages/csv_import/_preview.html @@ -25,6 +25,7 @@ [%- FOREACH row = SELF.data %] + [%- IF (SELF.profile.get('full_preview') == 2) || ((SELF.profile.get('full_preview') == 1) && (row.errors.size || row.information.size)) || ((SELF.profile.get('full_preview') == 0) && (loop.count < 21)) %] [%- FOREACH method = SELF.info_headers.methods %] [%- HTML.escape(row.info_data.$method) %] @@ -41,6 +42,7 @@ [%- END %] + [%- END %] [%- END %] diff --git a/templates/webpages/csv_import/form.html b/templates/webpages/csv_import/form.html index b146465a8..e835ed505 100644 --- a/templates/webpages/csv_import/form.html +++ b/templates/webpages/csv_import/form.html @@ -173,6 +173,15 @@ [%- INCLUDE 'csv_import/_form_customers_vendors.html' %] [%- END %] + + [%- LxERP.t8('Preview Mode') %]: + + [% L.radio_button_tag('settings.full_preview', value=2, checked=SELF.profile.get('full_preview')==2, label=LxERP.t8('Full Preview')) %] + [% L.radio_button_tag('settings.full_preview', value=1, checked=SELF.profile.get('full_preview')==1, label=LxERP.t8('Only Warnings and Errors')) %] + [% L.radio_button_tag('settings.full_preview', value=0, checked=!SELF.profile.get('full_preview'), label=LxERP.t8('First 20 Lines')) %] + + + [%- LxERP.t8('Import file') %]: [% L.input_tag('file', '', type => 'file', accept => '*') %]