login Layout
[kivitendo-erp.git] / SL / FCGIFixes.pm
1 package SL::FCGIFixes;
2
3 use strict;
4
5 use Encode;
6 use FCGI;
7 use version;
8
9 # FCGI does not use Perl's I/O layer. Therefore it does not honor
10 # setting STDOUT to ":utf8" with "binmode".  Also FCGI starting with
11 # 0.69 implements proper handling for UTF-8 flagged strings -- namely
12 # by downgrading them into bytes. The combination of the two causes
13 # Lx-Office's way of handling strings to go belly up (storing
14 # everything in Perl's internal encoding and using Perl's I/O layer
15 # for automatic conversion on output).
16 #
17 # This workaround monkeypatches FCGI's print routine so that all of
18 # its arguments safe for "$self" are encoded into UTF-8 before calling
19 # FCGI's original PRINT function.
20 #
21 # However, this must not be done if raw I/O is requested -- e.g. when
22 # sending out binary data. Fortunately that has been centralized via
23 # Locale's "with_raw_io" function which sets a variable indicating
24 # that current I/O operations should be raw.
25
26 sub fix_print_and_internal_encoding_after_0_68 {
27   return if version->new("$FCGI::VERSION")->numify <= version->new("0.68")->numify;
28   return if lc($::lx_office_conf{system}->{dbcharset}) !~ m/^(?:utf-?8|unicode)$/;
29
30   my $encoder             = Encode::find_encoding('UTF-8');
31   my $original_fcgi_print = \&FCGI::Stream::PRINT;
32
33   no warnings 'redefine';
34
35   *FCGI::Stream::PRINT = sub {
36     if (!$::locale || !$::locale->raw_io_active) {
37       my $self = shift;
38       my @vals = map { $encoder->encode($_, Encode::FB_CROAK|Encode::LEAVE_SRC) } @_;
39       @_ = ($self, @vals);
40     }
41
42     goto $original_fcgi_print;
43   };
44 }
45
46 sub apply_fixes {
47   fix_print_and_internal_encoding_after_0_68();
48 }
49
50 1;