From: Moritz Bunkus Date: Thu, 16 Jan 2014 14:37:48 +0000 (+0100) Subject: Archive::Zip::Member::_writeToFileHandle fixen X-Git-Tag: release-3.1.0beta1~21^2~4^2~1 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=fab47672ea774d7218190a2a536876727be5a5de;p=kivitendo-erp.git Archive::Zip::Member::_writeToFileHandle fixen Archive::Zip v1.31_04 und neuer enthält einen Bug, durch den von LibreOffice erzeugte ODTs beim Schreiben der neuen Datei zu einer Fehlermeldung, damit dem Abbruch der Schreiboperation und letztlich zu defekten Ausgabedateien führt. Der Bug existiert auch in der aktuellen Version 1.37. Daher die Funktion, in der die betroffene Änderung vorgenommen wurde, Monkeypatchen, bis der Bug behoben ist. Siehe https://rt.cpan.org/Public/Bug/Display.html?id=92205 --- diff --git a/SL/ArchiveZipFixes.pm b/SL/ArchiveZipFixes.pm new file mode 100644 index 000000000..ee5057965 --- /dev/null +++ b/SL/ArchiveZipFixes.pm @@ -0,0 +1,72 @@ +package SL::ArchiveZipFixes; + +use strict; + +use Archive::Zip; +use Archive::Zip::Member; +use version; + +# Archive::Zip contains a bug starting with 1.31_04 which prohibits +# re-writing Zips produced by LibreOffice (.odt). See +# https://rt.cpan.org/Public/Bug/Display.html?id=92205 + +sub _member_writeToFileHandle { + my $self = shift; + my $fh = shift; + my $fhIsSeekable = shift; + my $offset = shift; + + return _error("no member name given for $self") + if $self->fileName() eq ''; + + $self->{'writeLocalHeaderRelativeOffset'} = $offset; + $self->{'wasWritten'} = 0; + + # Determine if I need to write a data descriptor + # I need to do this if I can't refresh the header + # and I don't know compressed size or crc32 fields. + my $headerFieldsUnknown = ( + ( $self->uncompressedSize() > 0 ) + and ($self->compressionMethod() == Archive::Zip::COMPRESSION_STORED + or $self->desiredCompressionMethod() == Archive::Zip::COMPRESSION_DEFLATED ) + ); + + my $shouldWriteDataDescriptor = + ( $headerFieldsUnknown and not $fhIsSeekable ); + + $self->hasDataDescriptor(1) + if ($shouldWriteDataDescriptor); + + $self->{'writeOffset'} = 0; + + my $status = $self->rewindData(); + ( $status = $self->_writeLocalFileHeader($fh) ) + if $status == Archive::Zip::AZ_OK; + ( $status = $self->_writeData($fh) ) + if $status == Archive::Zip::AZ_OK; + if ( $status == Archive::Zip::AZ_OK ) { + $self->{'wasWritten'} = 1; + if ( $self->hasDataDescriptor() ) { + $status = $self->_writeDataDescriptor($fh); + } + elsif ($headerFieldsUnknown) { + $status = $self->_refreshLocalFileHeader($fh); + } + } + + return $status; +} + +sub fix_write_to_file_handle_1_30 { + return if version->new("$Archive::Zip::VERSION")->numify <= version->new("1.30")->numify; + + no warnings 'redefine'; + + *Archive::Zip::Member::_writeToFileHandle = \&_member_writeToFileHandle; +} + +sub apply_fixes { + fix_write_to_file_handle_1_30(); +} + +1; diff --git a/SL/Dispatcher.pm b/SL/Dispatcher.pm index fe992ed2a..f9ad09a87 100644 --- a/SL/Dispatcher.pm +++ b/SL/Dispatcher.pm @@ -26,6 +26,7 @@ use File::Basename; use List::MoreUtils qw(all); use List::Util qw(first); use POSIX; +use SL::ArchiveZipFixes; use SL::Auth; use SL::Dispatcher::AuthHandler; use SL::LXDebug; @@ -51,6 +52,8 @@ sub new { $self->{interface} = lc($interface || 'cgi'); $self->{auth_handler} = SL::Dispatcher::AuthHandler->new; + SL::ArchiveZipFixes->apply_fixes; + return $self; }