From fe77b2d593d067b88548da76a768df6c6c737176 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 22 Oct 2017 22:34:56 +0200 Subject: [PATCH] Add support for UTF8 filenames in wxZipOutputStream Zip filenames containing non ASCII characters will be marked with bit 11 in the general purpose flags and will use UTF-8 encoding. By only setting the flag when non ASCII characters are used the created archives should be binary identical to previous versions. The old behavior can be achieved by explicitly using wxConvLocal with the constructor. This should also ensure that existing code using a custom wxMBConv should work as before. --- docs/changes.txt | 4 ++++ include/wx/zipstrm.h | 6 ++++-- interface/wx/zipstrm.h | 11 +++++++++-- src/common/zipstrm.cpp | 18 ++++++++++++++---- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 91a0a3c018..886cb9c135 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -74,6 +74,9 @@ INCOMPATIBLE CHANGES SINCE 3.1.0: - The enum value wxTASKBAR_JUMP_LIST_DESTIONATION, which was added in 3.1.0, contains a typo and has been renamed to wxTASKBAR_JUMP_LIST_DESTINATION. + +- wxZipOutputStream will now automatically convert filenames to UTF-8, if the + wxMBConv used when calling the constructor supports UTF-8 encoding. All: @@ -98,6 +101,7 @@ All: - Add wxCMD_LINE_HIDDEN wxCmdLineParser flag (Lauri Nurmi). - Fix wxRmdir() with non-ASCII paths (trivia21). - Don't crash in wxFFile::Eof() or Error() on closed file (jprotopopov). +- Add UTF-8 support to wxZipOutputStream (Tobias Taschner). All (GUI): diff --git a/include/wx/zipstrm.h b/include/wx/zipstrm.h index ad07e42d64..9323cd101c 100644 --- a/include/wx/zipstrm.h +++ b/include/wx/zipstrm.h @@ -236,6 +236,8 @@ private: bool LoadExtraInfo(const char* extraData, wxUint16 extraLen, bool localInfo); + wxUint16 GetInternalFlags(bool checkForUTF8) const; + wxUint8 m_SystemMadeBy; // one of enum wxZipSystem wxUint8 m_VersionMadeBy; // major * 10 + minor @@ -278,10 +280,10 @@ class WXDLLIMPEXP_BASE wxZipOutputStream : public wxArchiveOutputStream public: wxZipOutputStream(wxOutputStream& stream, int level = -1, - wxMBConv& conv = wxConvLocal); + wxMBConv& conv = wxConvUTF8); wxZipOutputStream(wxOutputStream *stream, int level = -1, - wxMBConv& conv = wxConvLocal); + wxMBConv& conv = wxConvUTF8); virtual WXZIPFIX ~wxZipOutputStream(); bool PutNextEntry(wxZipEntry *entry) { return DoCreate(entry); } diff --git a/interface/wx/zipstrm.h b/interface/wx/zipstrm.h index fa21b1e986..8a787b7031 100644 --- a/interface/wx/zipstrm.h +++ b/interface/wx/zipstrm.h @@ -479,11 +479,18 @@ public: In a Unicode build the third parameter @a conv is used to translate the filename and comment fields to an 8-bit encoding. It has no effect on the stream's data. + + Since version 3.1.1, filenames in the generated archive will be encoded + using UTF-8 and marked according to ZIP specification. To get the + previous behaviour wxConvLocal may be provided as the conv object. + Please note that not all unzip applications are fully ZIP spec + compatible and may not correctly decode UTF-8 characters. For the best + interoperability using only ASCII characters is the safest option. */ wxZipOutputStream(wxOutputStream& stream, int level = -1, - wxMBConv& conv = wxConvLocal); + wxMBConv& conv = wxConvUTF8); wxZipOutputStream(wxOutputStream* stream, int level = -1, - wxMBConv& conv = wxConvLocal); + wxMBConv& conv = wxConvUTF8); //@} /** diff --git a/src/common/zipstrm.cpp b/src/common/zipstrm.cpp index 12be143e92..a63f34034b 100644 --- a/src/common/zipstrm.cpp +++ b/src/common/zipstrm.cpp @@ -1137,7 +1137,7 @@ size_t wxZipEntry::WriteLocal(wxOutputStream& stream, wxMBConv& conv) const wxDataOutputStream ds(stream); - ds << versionNeeded << m_Flags << m_Method; + ds << versionNeeded << GetInternalFlags(conv.IsUTF8()) << m_Method; ds.Write32(GetDateTime().GetAsDOS()); ds.Write32(m_Crc); @@ -1267,7 +1267,7 @@ size_t wxZipEntry::WriteCentral(wxOutputStream& stream, wxMBConv& conv) const ds << CENTRAL_MAGIC << m_VersionMadeBy << m_SystemMadeBy; ds.Write16(versionNeeded); - ds.Write16(wx_truncate_cast(wxUint16, GetFlags())); + ds.Write16(wx_truncate_cast(wxUint16, GetInternalFlags(conv.IsUTF8()))); ds.Write16(wx_truncate_cast(wxUint16, GetMethod())); ds.Write32(GetDateTime().GetAsDOS()); ds.Write32(GetCrc()); @@ -1359,6 +1359,16 @@ size_t wxZipEntry::WriteDescriptor(wxOutputStream& stream, wxUint32 crc, return SUMS_SIZE; } +// Returns the flags as specified or including the UTF-8 flag if filename +// contains non ASCII characters +wxUint16 wxZipEntry::GetInternalFlags(bool checkForUTF8) const +{ + wxUint16 flags = m_Flags; + if (checkForUTF8 && (!m_Name.IsAscii() || !m_Comment.IsAscii())) + flags |= wxZIP_LANG_ENC_UTF8; + + return flags; +} ///////////////////////////////////////////////////////////////////////////// // wxZipEndRec - holds the end of central directory record @@ -2115,7 +2125,7 @@ WX_DEFINE_LIST(wxZipEntryList_) wxZipOutputStream::wxZipOutputStream(wxOutputStream& stream, int level /*=-1*/, - wxMBConv& conv /*=wxConvLocal*/) + wxMBConv& conv /*=wxConvUTF8*/) : wxArchiveOutputStream(stream, conv) { Init(level); @@ -2123,7 +2133,7 @@ wxZipOutputStream::wxZipOutputStream(wxOutputStream& stream, wxZipOutputStream::wxZipOutputStream(wxOutputStream *stream, int level /*=-1*/, - wxMBConv& conv /*=wxConvLocal*/) + wxMBConv& conv /*=wxConvUTF8*/) : wxArchiveOutputStream(stream, conv) { Init(level);