]> wagnertech.de Git - mfinanz.git/commitdiff
Merge branch 'master' of vc.linet-services.de:public/lx-office-erp
authorSven Schöling <s.schoeling@linet-services.de>
Wed, 8 Aug 2012 15:48:29 +0000 (17:48 +0200)
committerSven Schöling <s.schoeling@linet-services.de>
Wed, 8 Aug 2012 15:48:29 +0000 (17:48 +0200)
SL/Request.pm
locale/de/all
scripts/task_server.pl
t/Support/TestSetup.pm
t/request/post_multipart.t [new file with mode: 0644]
t/request/post_multipart_1 [new file with mode: 0644]
templates/webpages/csv_import/_preview.html
templates/webpages/csv_import/form.html

index 64662875dc4e8ac6384b4e64f9a1fded5ab4a508..a8ae4c13702a0338d49a7418a19f1f662c5ff558 100644 (file)
@@ -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);
 }
 
index 9f31c8c669cc6a7c9fb4c8bc85a86e2b2c512c47..224cdfac591f7fda837d36b0d89cc85219a43c73 100644 (file)
@@ -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&szlig;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&auml;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&auml;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',
index f438b7410f6b12cd74b77f8dd00e6e4df8d6abfd..8c17ca70a6de97e4ada01f0250681b05459f618e 100755 (executable)
@@ -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;
 
index 5b6e2bb1fcfe3eb6491db397d1438b7dc9dd604f..cb8fd7ffb86bbb061be5bab771ac0b19a36aac40 100644 (file)
@@ -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 (file)
index 0000000..767807b
--- /dev/null
@@ -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 (file)
index 0000000..c3ced0f
--- /dev/null
@@ -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--
index fe088e25ecd31c448031737d3487013e84e679ab..01fe4d9ff2eff2ec2c3faf41eb8a750e199c8195 100644 (file)
@@ -25,6 +25,7 @@
   </tr>
 
   [%- 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)) %]
   <tr class="[% IF row.errors.size %]redrow[% ELSE %]listrow[% END %][% loop.count % 2 %]">
    [%- FOREACH method = SELF.info_headers.methods %]
     <td>[%- HTML.escape(row.info_data.$method) %]</td>
@@ -41,6 +42,7 @@
    </td>
   </tr>
   [%- END %]
+  [%- END %]
 
  </table>
 [%- END %]
index b146465a8bbba692c061b74106c9aa65218d35a9..e835ed505971b8d540a968743b25175a40b20372 100644 (file)
  [%- INCLUDE 'csv_import/_form_customers_vendors.html' %]
 [%- END %]
 
+   <tr>
+    <th align="right">[%- LxERP.t8('Preview Mode') %]:</th>
+    <td colspan="10">
+      [% 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')) %]
+    </td>
+   </tr>
+
    <tr>
     <th align="right">[%- LxERP.t8('Import file') %]:</th>
     <td colspan="10">[% L.input_tag('file', '', type => 'file', accept => '*') %]</td>