1 #====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #====================================================================
9 package SimpleTemplate;
12 # 1. The template's file name
13 # 2. A reference to the Form object
14 # 3. A reference to the myconfig hash
17 # A new template object
31 $self->{"source"} = shift;
32 $self->{"form"} = shift;
33 $self->{"myconfig"} = shift;
34 $self->{"userspath"} = shift;
36 $self->{"error"} = undef;
44 # 1. A typeglob for the file handle. The output will be written
45 # to this file handle.
48 # 1 on success and undef or 0 if there was an error. In the latter case
49 # the calling function can retrieve the error message via $obj->get_error()
54 print(OUT "Hallo!\n");
60 return $self->{"error"};
73 package LaTeXTemplate;
77 @ISA = qw(SimpleTemplate);
82 return $type->SUPER::new(@_);
86 my ($self, $variable) = @_;
87 my $form = $self->{"form"};
90 ('order' => [quotemeta("\\"),
93 '"', '\$', '%', '_', '#', quotemeta('^'),
94 '{', '}', '<', '>', '£', "\r", '±', '\xe1',
98 quotemeta("\\") => '\\textbackslash ',
113 '\xe1' => '$\bullet$',
114 quotemeta('^') => '\^\\',
115 quotemeta("\n") => '\newline ',
120 map({ $variable =~ s/$_/$replace{$_}/g; } @{ $replace{"order"} });
122 # Allow some HTML markup to be converted into the output format's
123 # corresponding markup code, e.g. bold or italic.
124 my %markup_replace = ('b' => 'textbf',
128 foreach my $key (keys(%markup_replace)) {
129 my $new = $markup_replace{$key};
130 $variable =~ s/\$\<\$${key}\$\>\$(.*?)\$<\$\/${key}\$>\$/\\${new}\{$1\}/gi;
133 $variable =~ s/[\x00-\x1f]//g;
138 sub substitute_vars {
139 my ($self, $text, @indices) = @_;
141 my $form = $self->{"form"};
143 while ($text =~ /<\%(.*?)\%>/) {
144 my ($var, @options) = split(/\s+/, $1);
145 my $value = $form->{$var};
147 for (my $i = 0; $i < scalar(@indices); $i++) {
148 last unless (ref($value) eq "ARRAY");
149 $value = $value->[$indices[$i]];
151 $value = $self->format_string($value) unless (grep(/^NOESCAPE$/, @options));
152 substr($text, $-[0], $+[0] - $-[0]) = $value;
159 my ($self, $var, $text, $start_tag, $end_tag, @indices) = @_;
161 my ($form, $new_contents) = ($self->{"form"}, "");
163 my $ary = $form->{$var};
164 for (my $i = 0; $i < scalar(@indices); $i++) {
165 last unless (ref($ary) eq "ARRAY");
166 $ary = $ary->[$indices[$i]];
170 my $current_page = 1;
171 my ($current_line, $corrent_row) = (0, 1);
173 for (my $i = 0; $i < scalar(@{$ary}); $i++) {
174 $form->{"__first__"} = $i == 0;
175 $form->{"__last__"} = ($i + 1) == scalar(@{$ary});
176 $form->{"__odd__"} = (($i + 1) % 2) == 1;
177 $form->{"__counter__"} = $i + 1;
179 if ((scalar(@{$form->{"description"}}) == scalar(@{$ary})) &&
180 $self->{"chars_per_line"}) {
182 int(length($form->{"description"}->[$i]) / $self->{"chars_per_line"});
185 $form->{"description"}->[$i] =~ s/(\\newline\s?)*$//;
186 my $_description = $form->{"description"}->[$i];
187 while ($_description =~ /\\newline/) {
189 $_description =~ s/\\newline//;
193 if ($current_page == 1) {
194 $lpp = $self->{"lines_on_first_page"};
196 $lpp = $self->{"lines_on_second_page"};
199 # Yes we need a manual page break -- or the user has forced one
200 if ((($current_line + $lines) > $lpp) ||
201 ($form->{"description"}->[$i] =~ /<pagebreak>/)) {
202 my $pb = $self->{"pagebreak_block"};
204 # replace the special variables <%sumcarriedforward%>
207 my $psum = $form->format_amount($self->{"myconfig"}, $sum, 2);
208 $pb =~ s/<%sumcarriedforward%>/$psum/g;
209 $pb =~ s/<%lastpage%>/$current_page/g;
211 my $new_text = $self->parse_block($pb, (@indices, $i));
212 return undef unless (defined($new_text));
213 $new_contents .= $new_text;
218 $current_line += $lines;
220 if ($i < scalar(@{$form->{"linetotal"}})) {
221 $sum += $form->parse_amount($self->{"myconfig"},
222 $form->{"linetotal"}->[$i]);
225 $form->{"cumulatelinetotal"}[$i] = $form->format_amount($self->{"myconfig"}, $sum, 2);
227 my $new_text = $self->parse_block($text, (@indices, $i));
228 return undef unless (defined($new_text));
229 $new_contents .= $start_tag . $new_text . $end_tag;
231 map({ delete($form->{"__${_}__"}); } qw(first last odd counter));
233 return $new_contents;
237 my ($self, $text, $pos, $var, $not) = @_;
240 $pos = 0 unless ($pos);
242 while ($pos < length($text)) {
245 next if (substr($text, $pos - 1, 2) ne '<%');
247 if ((substr($text, $pos + 1, 2) eq 'if') || (substr($text, $pos + 1, 3) eq 'for')) {
250 } elsif ((substr($text, $pos + 1, 4) eq 'else') && (1 == $depth)) {
252 $self->{"error"} = '<%else%> outside of <%if%> / <%ifnot%>.';
256 my $block = substr($text, 0, $pos - 1);
257 substr($text, 0, $pos - 1) = "";
258 $text =~ s!^<\%[^\%]+\%>!!;
259 $text = '<%if' . ($not ? " " : "not ") . $var . '%>' . $text;
261 return ($block, $text);
263 } elsif (substr($text, $pos + 1, 3) eq 'end') {
266 my $block = substr($text, 0, $pos - 1);
267 substr($text, 0, $pos - 1) = "";
268 $text =~ s!^<\%[^\%]+\%>!!;
270 return ($block, $text);
279 $main::lxdebug->enter_sub();
281 my ($self, $contents, @indices) = @_;
283 my $new_contents = "";
285 while ($contents ne "") {
286 my $pos_if = index($contents, '<%if');
287 my $pos_foreach = index($contents, '<%foreach');
289 if ((-1 == $pos_if) && (-1 == $pos_foreach)) {
290 $new_contents .= $self->substitute_vars($contents, @indices);
294 if ((-1 == $pos_if) || ((-1 != $pos_foreach) && ($pos_if > $pos_foreach))) {
295 $new_contents .= $self->substitute_vars(substr($contents, 0, $pos_foreach), @indices);
296 substr($contents, 0, $pos_foreach) = "";
298 if ($contents !~ m|^<\%foreach (.*?)\%>|) {
299 $self->{"error"} = "Malformed <\%foreach\%>.";
300 $main::lxdebug->leave_sub();
306 substr($contents, 0, length($&)) = "";
309 ($block, $contents) = $self->find_end($contents);
311 $self->{"error"} = "Unclosed <\%foreach\%>." unless ($self->{"error"});
312 $main::lxdebug->leave_sub();
316 my $new_text = $self->parse_foreach($var, $block, "", "", @indices);
317 if (!defined($new_text)) {
318 $main::lxdebug->leave_sub();
321 $new_contents .= $new_text;
324 $new_contents .= $self->substitute_vars(substr($contents, 0, $pos_if), @indices);
325 substr($contents, 0, $pos_if) = "";
327 if ($contents !~ m|^<\%if\s*(not)?\s+(.*?)\%>|) {
328 $self->{"error"} = "Malformed <\%if\%>.";
329 $main::lxdebug->leave_sub();
333 my ($not, $var) = ($1, $2);
335 substr($contents, 0, length($&)) = "";
337 ($block, $contents) = $self->find_end($contents, 0, $var, $not);
339 $self->{"error"} = "Unclosed <\%if${not}\%>." unless ($self->{"error"});
340 $main::lxdebug->leave_sub();
344 my $value = $self->{"form"}->{$var};
345 for (my $i = 0; $i < scalar(@indices); $i++) {
346 last unless (ref($value) eq "ARRAY");
347 $value = $value->[$indices[$i]];
350 if (($not && !$value) || (!$not && $value)) {
351 my $new_text = $self->parse_block($block, @indices);
352 if (!defined($new_text)) {
353 $main::lxdebug->leave_sub();
356 $new_contents .= $new_text;
361 $main::lxdebug->leave_sub();
363 return $new_contents;
369 my $form = $self->{"form"};
371 if (!open(IN, "$form->{templates}/$form->{IN}")) {
372 $self->{"error"} = "$!";
378 my $contents = join("", @_);
380 # detect pagebreak block and its parameters
381 if ($contents =~ /<%pagebreak\s+(\d+)\s+(\d+)\s+(\d+)\s*%>(.*?)<%end(\s*pagebreak)?%>/s) {
382 $self->{"chars_per_line"} = $1;
383 $self->{"lines_on_first_page"} = $2;
384 $self->{"lines_on_second_page"} = $3;
385 $self->{"pagebreak_block"} = $4;
387 substr($contents, length($`), length($&)) = "";
390 $self->{"forced_pagebreaks"} = [];
392 my $new_contents = $self->parse_block($contents);
393 if (!defined($new_contents)) {
394 $main::lxdebug->leave_sub();
398 print(OUT $new_contents);
400 if ($form->{"format"} =~ /postscript/i) {
401 return $self->convert_to_postscript();
402 } elsif ($form->{"format"} =~ /pdf/i) {
403 return $self->convert_to_pdf();
409 sub convert_to_postscript {
411 my ($form, $userspath) = ($self->{"form"}, $self->{"userspath"});
413 # Convert the tex file to postscript
415 if (!chdir("$userspath")) {
416 $self->{"error"} = "chdir : $!";
421 $form->{tmpfile} =~ s/$userspath\///g;
423 for (my $run = 1; $run <= 2; $run++) {
424 system("latex --interaction=nonstopmode $form->{tmpfile} " .
425 "> $form->{tmpfile}.err");
427 $self->{"error"} = $form->cleanup();
433 $form->{tmpfile} =~ s/tex$/dvi/;
435 system("dvips $form->{tmpfile} -o -q > /dev/null");
437 $self->{"error"} = "dvips : $!";
441 $form->{tmpfile} =~ s/dvi$/ps/;
450 my ($form, $userspath) = ($self->{"form"}, $self->{"userspath"});
452 # Convert the tex file to PDF
454 if (!chdir("$userspath")) {
455 $self->{"error"} = "chdir : $!";
460 $form->{tmpfile} =~ s/$userspath\///g;
462 for (my $run = 1; $run <= 2; $run++) {
463 system("pdflatex --interaction=nonstopmode $form->{tmpfile} " .
464 "> $form->{tmpfile}.err");
466 $self->{"error"} = $form->cleanup();
472 $form->{tmpfile} =~ s/tex$/pdf/;
477 sub get_mime_type() {
480 if ($self->{"form"}->{"format"} =~ /postscript/i) {
481 return "application/postscript";
483 return "application/pdf";
496 package HTMLTemplate;
500 @ISA = qw(LaTeXTemplate);
505 return $type->SUPER::new(@_);
509 my ($self, $variable) = @_;
510 my $form = $self->{"form"};
513 ('order' => ['<', '>', quotemeta("\n")],
516 quotemeta("\n") => '<br>',
519 map({ $variable =~ s/$_/$replace{$_}/g; } @{ $replace{"order"} });
521 # Allow some HTML markup to be converted into the output format's
522 # corresponding markup code, e.g. bold or italic.
523 my @markup_replace = ('b', 'i', 's', 'u', 'sub', 'sup');
525 foreach my $key (@markup_replace) {
526 $variable =~ s/\<(\/?)${key}\>/<$1${key}>/g;
532 sub get_mime_type() {
535 if ($self->{"form"}->{"format"} =~ /postscript/i) {
536 return "application/postscript";
537 } elsif ($self->{"form"}->{"format"} =~ /pdf/i) {
538 return "application/pdf";
547 if ($self->{"form"}->{"format"} =~ /postscript/i) {
549 } elsif ($self->{"form"}->{"format"} =~ /pdf/i) {
556 sub convert_to_postscript {
558 my ($form, $userspath) = ($self->{"form"}, $self->{"userspath"});
560 # Convert the HTML file to postscript
562 if (!chdir("$userspath")) {
563 $self->{"error"} = "chdir : $!";
568 $form->{"tmpfile"} =~ s/$userspath\///g;
569 my $psfile = $form->{"tmpfile"};
570 $psfile =~ s/.html/.ps/;
571 if ($psfile eq $form->{"tmpfile"}) {
575 system("html2ps -f html2ps-config < $form->{tmpfile} > $psfile");
577 $self->{"error"} = $form->cleanup();
582 $form->{"tmpfile"} = $psfile;
591 my ($form, $userspath) = ($self->{"form"}, $self->{"userspath"});
593 # Convert the HTML file to PDF
595 if (!chdir("$userspath")) {
596 $self->{"error"} = "chdir : $!";
601 $form->{"tmpfile"} =~ s/$userspath\///g;
602 my $pdffile = $form->{"tmpfile"};
603 $pdffile =~ s/.html/.pdf/;
604 if ($pdffile eq $form->{"tmpfile"}) {
608 system("html2ps -f html2ps-config < $form->{tmpfile} | ps2pdf - $pdffile");
610 $self->{"error"} = $form->cleanup();
615 $form->{"tmpfile"} = $pdffile;
624 #### PlainTextTemplate
627 package PlainTextTemplate;
631 @ISA = qw(LaTeXTemplate);
636 return $type->SUPER::new(@_);
640 my ($self, $variable) = @_;
655 #### OpenDocumentTemplate
658 package OpenDocumentTemplate;
666 # use File::Temp qw(:mktemp);
669 @ISA = qw(SimpleTemplate);
674 $self = $type->SUPER::new(@_);
676 foreach my $module (qw(Archive::Zip Text::Iconv)) {
677 eval("use ${module};");
679 $self->{"form"}->error("The Perl module '${module}' could not be " .
680 "loaded. Support for OpenDocument templates " .
681 "does not work without it. Please install your " .
682 "distribution's package or get the module from " .
683 "CPAN ( http://www.cpan.org ).");
687 $self->{"rnd"} = int(rand(1000000));
688 $self->{"iconv"} = Text::Iconv->new($main::dbcharset, "UTF-8");
693 sub substitute_vars {
694 my ($self, $text, @indices) = @_;
696 my $form = $self->{"form"};
698 while ($text =~ /\<\%(.*?)\%\>/) {
699 my $value = $form->{$1};
701 for (my $i = 0; $i < scalar(@indices); $i++) {
702 last unless (ref($value) eq "ARRAY");
703 $value = $value->[$indices[$i]];
705 substr($text, $-[0], $+[0] - $-[0]) = $self->format_string($value);
712 my ($self, $var, $text, $start_tag, $end_tag, @indices) = @_;
714 my ($form, $new_contents) = ($self->{"form"}, "");
716 my $ary = $form->{$var};
717 for (my $i = 0; $i < scalar(@indices); $i++) {
718 last unless (ref($ary) eq "ARRAY");
719 $ary = $ary->[$indices[$i]];
722 for (my $i = 0; $i < scalar(@{$ary}); $i++) {
723 $form->{"__first__"} = $i == 0;
724 $form->{"__last__"} = ($i + 1) == scalar(@{$ary});
725 $form->{"__odd__"} = (($i + 1) % 2) == 1;
726 $form->{"__counter__"} = $i + 1;
727 my $new_text = $self->parse_block($text, (@indices, $i));
728 return undef unless (defined($new_text));
729 $new_contents .= $start_tag . $new_text . $end_tag;
731 map({ delete($form->{"__${_}__"}); } qw(first last odd counter));
733 return $new_contents;
737 my ($self, $text, $pos, $var, $not) = @_;
740 $pos = 0 unless ($pos);
742 while ($pos < length($text)) {
745 next if (substr($text, $pos - 1, 5) ne '<%');
747 if ((substr($text, $pos + 4, 2) eq 'if') || (substr($text, $pos + 4, 3) eq 'for')) {
750 } elsif ((substr($text, $pos + 4, 4) eq 'else') && (1 == $depth)) {
752 $self->{"error"} = '<%else%> outside of <%if%> / <%ifnot%>.';
756 my $block = substr($text, 0, $pos - 1);
757 substr($text, 0, $pos - 1) = "";
758 $text =~ s!^\<\%[^\%]+\%\>!!;
759 $text = '<%if' . ($not ? " " : "not ") . $var . '%>' . $text;
761 return ($block, $text);
763 } elsif (substr($text, $pos + 4, 3) eq 'end') {
766 my $block = substr($text, 0, $pos - 1);
767 substr($text, 0, $pos - 1) = "";
768 $text =~ s!^\<\%[^\%]+\%\>!!;
770 return ($block, $text);
779 $main::lxdebug->enter_sub();
781 my ($self, $contents, @indices) = @_;
783 my $new_contents = "";
785 while ($contents ne "") {
786 if (substr($contents, 0, 1) eq "<") {
787 $contents =~ m|^<[^>]+>|;
789 substr($contents, 0, length($&)) = "";
791 if ($tag =~ m|<table:table-row|) {
792 $contents =~ m|^(.*?)(</table:table-row[^>]*>)|;
795 substr($contents, 0, length($1) + length($end_tag)) = "";
797 if ($table_row =~ m|\<\%foreachrow\s+(.*?)\%\>|) {
800 substr($table_row, length($`), length($&)) = "";
802 my ($t1, $t2) = $self->find_end($table_row, length($`));
804 $self->{"error"} = "Unclosed <\%foreachrow\%>." unless ($self->{"error"});
805 $main::lxdebug->leave_sub();
809 my $new_text = $self->parse_foreach($var, $t1 . $t2, $tag, $end_tag, @indices);
810 if (!defined($new_text)) {
811 $main::lxdebug->leave_sub();
814 $new_contents .= $new_text;
817 my $new_text = $self->parse_block($table_row, @indices);
818 if (!defined($new_text)) {
819 $main::lxdebug->leave_sub();
822 $new_contents .= $tag . $new_text . $end_tag;
826 $new_contents .= $tag;
830 $contents =~ /^[^<]+/;
833 my $pos_if = index($text, '<%if');
834 my $pos_foreach = index($text, '<%foreach');
836 if ((-1 == $pos_if) && (-1 == $pos_foreach)) {
837 substr($contents, 0, length($text)) = "";
838 $new_contents .= $self->substitute_vars($text, @indices);
842 if ((-1 == $pos_if) || ((-1 != $pos_foreach) && ($pos_if > $pos_foreach))) {
843 $new_contents .= $self->substitute_vars(substr($contents, 0, $pos_foreach), @indices);
844 substr($contents, 0, $pos_foreach) = "";
846 if ($contents !~ m|^\<\%foreach (.*?)\%\>|) {
847 $self->{"error"} = "Malformed <\%foreach\%>.";
848 $main::lxdebug->leave_sub();
854 substr($contents, 0, length($&)) = "";
857 ($block, $contents) = $self->find_end($contents);
859 $self->{"error"} = "Unclosed <\%foreach\%>." unless ($self->{"error"});
860 $main::lxdebug->leave_sub();
864 my $new_text = $self->parse_foreach($var, $block, "", "", @indices);
865 if (!defined($new_text)) {
866 $main::lxdebug->leave_sub();
869 $new_contents .= $new_text;
872 $new_contents .= $self->substitute_vars(substr($contents, 0, $pos_if), @indices);
873 substr($contents, 0, $pos_if) = "";
875 if ($contents !~ m|^\<\%if\s*(not)?\s+(.*?)\%\>|) {
876 $self->{"error"} = "Malformed <\%if\%>.";
877 $main::lxdebug->leave_sub();
881 my ($not, $var) = ($1, $2);
883 substr($contents, 0, length($&)) = "";
885 ($block, $contents) = $self->find_end($contents, 0, $var, $not);
887 $self->{"error"} = "Unclosed <\%if${not}\%>." unless ($self->{"error"});
888 $main::lxdebug->leave_sub();
892 my $value = $self->{"form"}->{$var};
893 for (my $i = 0; $i < scalar(@indices); $i++) {
894 last unless (ref($value) eq "ARRAY");
895 $value = $value->[$indices[$i]];
898 if (($not && !$value) || (!$not && $value)) {
899 my $new_text = $self->parse_block($block, @indices);
900 if (!defined($new_text)) {
901 $main::lxdebug->leave_sub();
904 $new_contents .= $new_text;
910 $main::lxdebug->leave_sub();
912 return $new_contents;
916 $main::lxdebug->enter_sub();
920 my $form = $self->{"form"};
925 if ($form->{"IN"} =~ m|^/|) {
926 $file_name = $form->{"IN"};
928 $file_name = $form->{"templates"} . "/" . $form->{"IN"};
931 my $zip = Archive::Zip->new();
932 if (Archive::Zip::AZ_OK != $zip->read($file_name)) {
933 $self->{"error"} = "File not found/is not a OpenDocument file.";
934 $main::lxdebug->leave_sub();
938 my $contents = $zip->contents("content.xml");
940 $self->{"error"} = "File is not a OpenDocument file.";
941 $main::lxdebug->leave_sub();
945 my $rnd = $self->{"rnd"};
946 my $new_styles = qq|<style:style style:name="TLXO${rnd}BOLD" style:family="text">
947 <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
949 <style:style style:name="TLXO${rnd}ITALIC" style:family="text">
950 <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/>
952 <style:style style:name="TLXO${rnd}UNDERLINE" style:family="text">
953 <style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
955 <style:style style:name="TLXO${rnd}STRIKETHROUGH" style:family="text">
956 <style:text-properties style:text-line-through-style="solid"/>
958 <style:style style:name="TLXO${rnd}SUPER" style:family="text">
959 <style:text-properties style:text-position="super 58%"/>
961 <style:style style:name="TLXO${rnd}SUB" style:family="text">
962 <style:text-properties style:text-position="sub 58%"/>
966 $contents =~ s|</office:automatic-styles>|${new_styles}</office:automatic-styles>|;
967 $contents =~ s|[\n\r]||gm;
969 my $new_contents = $self->parse_block($contents);
970 if (!defined($new_contents)) {
971 $main::lxdebug->leave_sub();
975 # $new_contents =~ s|>|>\n|g;
977 $zip->contents("content.xml", $new_contents);
979 my $styles = $zip->contents("styles.xml");
981 my $new_styles = $self->parse_block($styles);
982 if (!defined($new_contents)) {
983 $main::lxdebug->leave_sub();
986 $zip->contents("styles.xml", $new_styles);
989 $zip->writeToFileNamed($form->{"tmpfile"}, 1);
992 if ($form->{"format"} =~ /pdf/) {
993 $res = $self->convert_to_pdf();
996 $main::lxdebug->leave_sub();
1000 sub is_xvfb_running {
1001 $main::lxdebug->enter_sub();
1006 my $dfname = $self->{"userspath"} . "/xvfb_display";
1009 $main::lxdebug->message(LXDebug::DEBUG2, " Looking for $dfname\n");
1010 if ((-f $dfname) && open(IN, $dfname)) {
1015 my $xauthority = <IN>;
1019 $main::lxdebug->message(LXDebug::DEBUG2, " found with $pid and $display\n");
1021 if ((! -d "/proc/$pid") || !open(IN, "/proc/$pid/cmdline")) {
1022 $main::lxdebug->message(LXDebug::DEBUG2, " no/wrong process #1\n");
1023 unlink($dfname, $xauthority);
1024 $main::lxdebug->leave_sub();
1029 if ($line !~ /xvfb/i) {
1030 $main::lxdebug->message(LXDebug::DEBUG2, " no/wrong process #2\n");
1031 unlink($dfname, $xauthority);
1032 $main::lxdebug->leave_sub();
1036 $ENV{"XAUTHORITY"} = $xauthority;
1037 $ENV{"DISPLAY"} = $display;
1039 $main::lxdebug->message(LXDebug::DEBUG2, " not found\n");
1042 $main::lxdebug->leave_sub();
1048 $main::lxdebug->enter_sub();
1052 $main::lxdebug->message(LXDebug::DEBUG2, "spawn_xvfb()\n");
1054 my $display = $self->is_xvfb_running();
1057 $main::lxdebug->leave_sub();
1062 while ( -f "/tmp/.X${display}-lock") {
1065 $display = ":${display}";
1066 $main::lxdebug->message(LXDebug::DEBUG2, " display $display\n");
1068 my $mcookie = `mcookie`;
1069 die("Installation error: mcookie not found.") if ($? != 0);
1072 $main::lxdebug->message(LXDebug::DEBUG2, " mcookie $mcookie\n");
1074 my $xauthority = "/tmp/.Xauthority-" . $$ . "-" . time() . "-" . int(rand(9999999));
1075 $ENV{"XAUTHORITY"} = $xauthority;
1077 $main::lxdebug->message(LXDebug::DEBUG2, " xauthority $xauthority\n");
1079 system("xauth add \"${display}\" . \"${mcookie}\"");
1081 $self->{"error"} = "Conversion to PDF failed because OpenOffice could not be started (xauth: $!)";
1082 $main::lxdebug->leave_sub();
1086 $main::lxdebug->message(LXDebug::DEBUG2, " about to fork()\n");
1090 $main::lxdebug->message(LXDebug::DEBUG2, " Child execing\n");
1091 exec($main::xvfb_bin, $display, "-screen", "0", "640x480x8", "-nolisten", "tcp");
1094 $main::lxdebug->message(LXDebug::DEBUG2, " parent dont sleeping\n");
1097 my $dfname = $self->{"userspath"} . "/xvfb_display";
1098 if (!open(OUT, ">$dfname")) {
1099 $self->{"error"} = "Conversion to PDF failed because OpenOffice could not be started ($dfname: $!)";
1100 unlink($xauthority);
1102 $main::lxdebug->leave_sub();
1105 print(OUT "$pid\n$display\n$xauthority\n");
1108 $main::lxdebug->message(LXDebug::DEBUG2, " parent re-testing\n");
1110 if (!$self->is_xvfb_running()) {
1111 $self->{"error"} = "Conversion to PDF failed because OpenOffice could not be started.";
1112 unlink($xauthority, $dfname);
1114 $main::lxdebug->leave_sub();
1118 $main::lxdebug->message(LXDebug::DEBUG2, " spawn OK\n");
1120 $main::lxdebug->leave_sub();
1125 sub is_openoffice_running {
1126 $main::lxdebug->enter_sub();
1128 system("./scripts/oo-uno-test-conn.py $main::openofficeorg_daemon_port " .
1129 "> /dev/null 2> /dev/null");
1131 $main::lxdebug->message(LXDebug::DEBUG2, " is_openoffice_running(): $?\n");
1133 $main::lxdebug->leave_sub();
1138 sub spawn_openoffice {
1139 $main::lxdebug->enter_sub();
1143 $main::lxdebug->message(LXDebug::DEBUG2, "spawn_openoffice()\n");
1145 my ($try, $spawned_oo, $res);
1148 for ($try = 0; $try < 15; $try++) {
1149 if ($self->is_openoffice_running()) {
1157 $main::lxdebug->message(LXDebug::DEBUG2, " Child daemonizing\n");
1159 open(STDIN, '/dev/null');
1160 open(STDOUT, '>/dev/null');
1161 my $new_pid = fork();
1163 my $ssres = setsid();
1164 $main::lxdebug->message(LXDebug::DEBUG2, " Child execing\n");
1165 my @cmdline = ($main::openofficeorg_writer_bin,
1166 "-minimized", "-norestore", "-nologo", "-nolockcheck",
1168 "-accept=socket,host=localhost,port=" .
1169 $main::openofficeorg_daemon_port . ";urp;");
1173 $main::lxdebug->message(LXDebug::DEBUG2, " Parent after fork\n");
1178 sleep($try >= 5 ? 2 : 1);
1182 $self->{"error"} = "Conversion from OpenDocument to PDF failed because " .
1183 "OpenOffice could not be started.";
1186 $main::lxdebug->leave_sub();
1191 sub convert_to_pdf {
1192 $main::lxdebug->enter_sub();
1196 my $form = $self->{"form"};
1198 my $filename = $form->{"tmpfile"};
1199 $filename =~ s/.odt$//;
1200 if (substr($filename, 0, 1) ne "/") {
1201 $filename = getcwd() . "/${filename}";
1204 if (substr($self->{"userspath"}, 0, 1) eq "/") {
1205 $ENV{'HOME'} = $self->{"userspath"};
1207 $ENV{'HOME'} = getcwd() . "/" . $self->{"userspath"};
1210 if (!$self->spawn_xvfb()) {
1211 $main::lxdebug->leave_sub();
1216 if (!$main::openofficeorg_daemon) {
1217 @cmdline = ($main::openofficeorg_writer_bin,
1218 "-minimized", "-norestore", "-nologo", "-nolockcheck",
1220 "file:${filename}.odt",
1221 "macro://" . (split('/', $filename))[-1] .
1222 "/Standard.Conversion.ConvertSelfToPDF()");
1224 if (!$self->spawn_openoffice()) {
1225 $main::lxdebug->leave_sub();
1229 @cmdline = ("./scripts/oo-uno-convert-pdf.py",
1230 $main::openofficeorg_daemon_port,
1238 $form->{"tmpfile"} =~ s/odt$/pdf/;
1240 unlink($filename . ".odt");
1242 $main::lxdebug->leave_sub();
1247 unlink($filename . ".odt", $filename . ".pdf");
1248 $self->{"error"} = "Conversion from OpenDocument to PDF failed. " .
1251 $main::lxdebug->leave_sub();
1256 my ($self, $variable) = @_;
1257 my $form = $self->{"form"};
1258 my $iconv = $self->{"iconv"};
1261 ('order' => ['&', '<', '>', '"', "'",
1263 quotemeta("\n"), quotemeta("\r")],
1269 '\x80' => chr(0xa4), # Euro
1270 quotemeta("\n") => '<text:line-break/>',
1271 quotemeta("\r") => '',
1274 map({ $variable =~ s/$_/$replace{$_}/g; } @{ $replace{"order"} });
1276 # Allow some HTML markup to be converted into the output format's
1277 # corresponding markup code, e.g. bold or italic.
1278 my $rnd = $self->{"rnd"};
1279 my %markup_replace = ("b" => "BOLD", "i" => "ITALIC", "s" => "STRIKETHROUGH",
1280 "u" => "UNDERLINE", "sup" => "SUPER", "sub" => "SUB");
1282 foreach my $key (keys(%markup_replace)) {
1283 my $value = $markup_replace{$key};
1284 $variable =~ s|\<${key}\>|<text:span text:style-name=\"TLXO${rnd}${value}\">|gi;
1285 $variable =~ s|\</${key}\>|</text:span>|gi;
1288 return $iconv->convert($variable);
1291 sub get_mime_type() {
1292 if ($self->{"form"}->{"format"} =~ /pdf/) {
1293 return "application/pdf";
1295 return "application/vnd.oasis.opendocument.text";
1299 sub uses_temp_file {
1304 ##########################################################
1308 ##########################################################
1310 package XMLTemplate;
1314 @ISA = qw(HTMLTemplate);
1317 #evtl auskommentieren
1320 return $type->SUPER::new(@_);
1324 my ($self, $variable) = @_;
1325 my $form = $self->{"form"};
1328 ('order' => ['<', '>', quotemeta("\n")],
1331 quotemeta("\n") => '<br>',
1334 map({ $variable =~ s/$_/$replace{$_}/g; } @{ $replace{"order"} });
1336 # Allow no markup to be converted into the output format
1337 my @markup_replace = ('b', 'i', 's', 'u', 'sub', 'sup');
1339 foreach my $key (@markup_replace) {
1340 $variable =~ s/\<(\/?)${key}\>//g;
1346 sub get_mime_type() {
1349 if ($self->{"form"}->{"format"} =~ /elsterwinston/i) {
1350 return "application/xml ";
1351 } elsif ($self->{"form"}->{"format"} =~ /elstertaxbird/i) {
1352 return "application/x-taxbird";
1358 sub uses_temp_file {
1359 # tempfile needet for XML Output