Merge branch 'master' into dev
[kivitendo-erp.git] / SL / Template / OpenDocument.pm
index 626d3c0..f9507f9 100644 (file)
@@ -3,6 +3,7 @@ package SL::Template::OpenDocument;
 use parent qw(SL::Template::Simple);
 
 use Archive::Zip;
+use Encode;
 use POSIX 'setsid';
 
 use SL::Iconv;
@@ -21,7 +22,7 @@ sub new {
   my $self = $type->SUPER::new(@_);
 
   $self->{"rnd"}   = int(rand(1000000));
-  $self->{"iconv"} = SL::Iconv->new($main::dbcharset, "UTF-8");
+  $self->{"iconv"} = SL::Iconv->new($::lx_office_conf{system}->{dbcharset}, "UTF-8");
 
   $self->set_tag_style('<%', '%>');
   $self->{quot_re} = '"';
@@ -36,7 +37,7 @@ sub parse_foreach {
 
   my $ary = $self->_get_loop_variable($var, 1, @indices);
 
-  for (my $i = 0; $i < scalar(@{$ary}); $i++) {
+  for (my $i = 0; $i < scalar(@{$ary || []}); $i++) {
     $form->{"__first__"} = $i == 0;
     $form->{"__last__"} = ($i + 1) == scalar(@{$ary});
     $form->{"__odd__"} = (($i + 1) % 2) == 1;
@@ -109,21 +110,27 @@ sub parse_block {
         $contents =~ m|^(.*?)(</table:table-row[^>]*>)|;
         my $table_row = $1;
         my $end_tag = $2;
-        substr($contents, 0, length($1) + length($end_tag)) = "";
 
         if ($table_row =~ m|\&lt;\%foreachrow\s+(.*?)\%\&gt;|) {
           my $var = $1;
 
-          substr($table_row, length($`), length($&)) = "";
+          $contents =~ m|\&lt;\%foreachrow\s+.*?\%\&gt;|;
+          substr($contents, length($`), length($&)) = "";
 
-          my ($t1, $t2) = $self->find_end($table_row, length($`));
-          if (!$t1) {
+          ($table_row, $contents) = $self->find_end($contents, length($`));
+          if (!$table_row) {
             $self->{"error"} = "Unclosed <\%foreachrow\%>." unless ($self->{"error"});
             $main::lxdebug->leave_sub();
             return undef;
           }
 
-          my $new_text = $self->parse_foreach($var, $t1 . $t2, $tag, $end_tag, @indices);
+          $contents   =~ m|^(.*?)(</table:table-row[^>]*>)|;
+          $table_row .=  $1;
+          $end_tag    =  $2;
+
+          substr $contents, 0, length($&), '';
+
+          my $new_text = $self->parse_foreach($var, $table_row, $tag, $end_tag, @indices);
           if (!defined($new_text)) {
             $main::lxdebug->leave_sub();
             return undef;
@@ -131,6 +138,7 @@ sub parse_block {
           $new_contents .= $new_text;
 
         } else {
+          substr($contents, 0, length($table_row) + length($end_tag)) = "";
           my $new_text = $self->parse_block($table_row, @indices);
           if (!defined($new_text)) {
             $main::lxdebug->leave_sub();
@@ -221,7 +229,7 @@ sub parse {
     return 0;
   }
 
-  my $contents = $zip->contents("content.xml");
+  my $contents = Encode::decode('utf-8-strict', $zip->contents("content.xml"));
   if (!$contents) {
     $self->{"error"} = "File is not a OpenDocument file.";
     $main::lxdebug->leave_sub();
@@ -260,16 +268,16 @@ sub parse {
 
 #   $new_contents =~ s|>|>\n|g;
 
-  $zip->contents("content.xml", $new_contents);
+  $zip->contents("content.xml", Encode::encode('utf-8-strict', $new_contents));
 
-  my $styles = $zip->contents("styles.xml");
+  my $styles = Encode::decode('utf-8-strict', $zip->contents("styles.xml"));
   if ($contents) {
     my $new_styles = $self->parse_block($styles);
     if (!defined($new_contents)) {
       $main::lxdebug->leave_sub();
       return 0;
     }
-    $zip->contents("styles.xml", $new_styles);
+    $zip->contents("styles.xml", Encode::encode('utf-8-strict', $new_styles));
   }
 
   $zip->writeToFileNamed($form->{"tmpfile"}, 1);
@@ -374,14 +382,14 @@ sub spawn_xvfb {
   my $pid = fork();
   if (0 == $pid) {
     $main::lxdebug->message(LXDebug->DEBUG2(), "  Child execing\n");
-    exec($main::xvfb_bin, $display, "-screen", "0", "640x480x8", "-nolisten", "tcp");
+    exec($::lx_office_conf{applications}->{xvfb}, $display, "-screen", "0", "640x480x8", "-nolisten", "tcp");
   }
   sleep(3);
   $main::lxdebug->message(LXDebug->DEBUG2(), "  parent dont sleeping\n");
 
   local *OUT;
   my $dfname = $self->{"userspath"} . "/xvfb_display";
-  if (!open(OUT, ">$dfname")) {
+  if (!open(OUT, ">", $dfname)) {
     $self->{"error"} = "Conversion to PDF failed because OpenOffice could not be started ($dfname: $!)";
     unlink($xauthority);
     kill($pid);
@@ -408,10 +416,21 @@ sub spawn_xvfb {
   return $display;
 }
 
+sub _run_python_uno {
+  my ($self, @args) = @_;
+
+  local $ENV{PYTHONPATH};
+  $ENV{PYTHONPATH} = $::lx_office_conf{environment}->{python_uno_path} . ':' . $ENV{PYTHONPATH} if $::lx_office_conf{environment}->{python_uno_path};
+  my $cmd          = $::lx_office_conf{applications}->{python_uno} . ' ' . join(' ', @args);
+  return `$cmd`;
+}
+
 sub is_openoffice_running {
+  my ($self) = @_;
+
   $main::lxdebug->enter_sub();
 
-  my $output = `./scripts/oo-uno-test-conn.py $main::openofficeorg_daemon_port 2> /dev/null`;
+  my $output = $self->_run_python_uno('./scripts/oo-uno-test-conn.py', $::lx_office_conf{print_templates}->{openofficeorg_daemon_port}, ' 2> /dev/null');
   chomp $output;
 
   my $res = ($? == 0) || $output;
@@ -438,10 +457,19 @@ sub spawn_openoffice {
       last;
     }
 
+    if ($::dispatcher->interface_type eq 'FastCGI') {
+      $::dispatcher->{request}->Detach;
+    }
+
     if (!$spawned_oo) {
       my $pid = fork();
       if (0 == $pid) {
         $main::lxdebug->message(LXDebug->DEBUG2(), "  Child daemonizing\n");
+
+        if ($::dispatcher->interface_type eq 'FastCGI') {
+          $::dispatcher->{request}->Finish;
+          $::dispatcher->{request}->LastCall;
+        }
         chdir('/');
         open(STDIN, '/dev/null');
         open(STDOUT, '>/dev/null');
@@ -449,12 +477,17 @@ sub spawn_openoffice {
         exit if ($new_pid);
         my $ssres = setsid();
         $main::lxdebug->message(LXDebug->DEBUG2(), "  Child execing\n");
-        my @cmdline = ($main::openofficeorg_writer_bin,
+        my @cmdline = ($::lx_office_conf{applications}->{openofficeorg_writer},
                        "-minimized", "-norestore", "-nologo", "-nolockcheck",
                        "-headless",
                        "-accept=socket,host=localhost,port=" .
-                       $main::openofficeorg_daemon_port . ";urp;");
+                       $::lx_office_conf{print_templates}->{openofficeorg_daemon_port} . ";urp;");
         exec(@cmdline);
+      } else {
+        # parent
+        if ($::dispatcher->interface_type eq 'FastCGI') {
+          $::dispatcher->{request}->Attach;
+        }
       }
 
       $main::lxdebug->message(LXDebug->DEBUG2(), "  Parent after fork\n");
@@ -499,27 +532,20 @@ sub convert_to_pdf {
     return 0;
   }
 
-  my @cmdline;
-  if (!$main::openofficeorg_daemon) {
-    @cmdline = ($main::openofficeorg_writer_bin,
-                "-minimized", "-norestore", "-nologo", "-nolockcheck",
-                "-headless",
-                "file:${filename}.odt",
-                "macro://" . (split('/', $filename))[-1] .
-                "/Standard.Conversion.ConvertSelfToPDF()");
+  if (!$::lx_office_conf{print_templates}->{openofficeorg_daemon}) {
+    system($::lx_office_conf{applications}->{openofficeorg_writer},
+           "-minimized", "-norestore", "-nologo", "-nolockcheck", "-headless",
+           "file:${filename}.odt",
+           "macro://" . (split('/', $filename))[-1] . "/Standard.Conversion.ConvertSelfToPDF()");
   } else {
     if (!$self->spawn_openoffice()) {
       $main::lxdebug->leave_sub();
       return 0;
     }
 
-    @cmdline = ("./scripts/oo-uno-convert-pdf.py",
-                $main::openofficeorg_daemon_port,
-                "${filename}.odt");
+    $self->_run_python_uno('./scripts/oo-uno-convert-pdf.py', $::lx_office_conf{print_templates}->{openofficeorg_daemon_port}, "${filename}.odt");
   }
 
-  system(@cmdline);
-
   my $res = $?;
   if ((0 == $?) || (-f "${filename}.pdf" && -s "${filename}.pdf")) {
     $form->{"tmpfile"} =~ s/odt$/pdf/;