Skip to content

Commit 7daa17c

Browse files
authored
Merge pull request #2 from mplpl/encoding
File names encoding can be set for zip, rar, arj, lha
2 parents 4a2154e + 88b2d97 commit 7daa17c

21 files changed

+489
-172
lines changed

lib7z/lib7z.cpp

+41-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Main.cpp
2-
// Copyright @ 2016 MPL. All rights reserved.
2+
// Copyright @ 2016-2020 MPL. All rights reserved.
33

44
#include "StdAfx.h"
55

@@ -21,6 +21,8 @@
2121
#include <string>
2222
#include <sstream>
2323

24+
#include <iconv.h>
25+
2426
namespace lib7z
2527
{
2628

@@ -35,9 +37,9 @@ static void GetAttribString(DWORD wa, bool isDir, char *s)
3537
s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': '.';
3638
s[5] = 0;
3739
}
38-
39-
LIB7ZRC MLListArchive(std::wstring archiveNameW, std::vector<DirectoryItem> &retValue, MLListCallback &callback)
40-
{
40+
41+
LIB7ZRC MLListArchive(std::wstring archiveNameW, std::vector<DirectoryItem> &retValue, MLListCallback &callback, std::wstring encoding)
42+
{
4143
UString archiveName = archiveNameW.c_str();
4244
NWindows::NFile::NFind::CFileInfo fi;
4345
if (!fi.Find(archiveName) || fi.IsDir())
@@ -58,7 +60,11 @@ LIB7ZRC MLListArchive(std::wstring archiveNameW, std::vector<DirectoryItem> &ret
5860
MLListCallbackWrapper openCallback(callback);
5961
COpenOptions openOptions;
6062
CObjectVector<CProperty> props;
61-
63+
if (!encoding.empty())
64+
{
65+
CProperty prop ={L"cps", encoding.c_str()};
66+
props.Add(prop);
67+
}
6268
openOptions.codecs = &codecs;
6369
openOptions.filePath = archiveName;
6470
openOptions.excludedFormats = &formatIndices;
@@ -132,7 +138,7 @@ LIB7ZRC MLListArchive(std::wstring archiveNameW, std::vector<DirectoryItem> &ret
132138

133139

134140
LIB7ZRC MLExtractFromArchive(std::wstring archiveNameW, std::wstring outDirW, std::vector<std::wstring> files,
135-
MLExtractCallback &callback, std::wstring workDir)
141+
MLExtractCallback &callback, std::wstring workDir, std::wstring encoding)
136142
{
137143
UString archiveName = archiveNameW.c_str();
138144
UString outDir = outDirW.c_str();
@@ -154,6 +160,11 @@ LIB7ZRC MLExtractFromArchive(std::wstring archiveNameW, std::wstring outDirW, st
154160
CIntVector formatIndices;
155161
CObjectVector<COpenType> types;
156162
CObjectVector<CProperty> props;
163+
if (!encoding.empty())
164+
{
165+
CProperty prop ={L"cps", L"CP852"};
166+
props.Add(prop);
167+
}
157168
MLListCallbackWrapper openCallback(callback);
158169
COpenOptions openOptions;
159170
openOptions.codecs = &codecs;
@@ -265,7 +276,7 @@ LIB7ZRC MLExtractFromArchive(std::wstring archiveNameW, std::wstring outDirW, st
265276

266277

267278
LIB7ZRC MLGenericCommand(std::wstring command, std::wstring archiveNameW, std::vector<std::wstring> filesW, MLUpdateCallback &cb,
268-
bool encryptHeader, int compressionLevel, std::wstring workDir)
279+
bool encryptHeader, int compressionLevel, std::wstring workDir, std::wstring encoding)
269280
{
270281
UString archiveName = archiveNameW.c_str();
271282
std::vector<UString> files;
@@ -294,6 +305,10 @@ LIB7ZRC MLGenericCommand(std::wstring command, std::wstring archiveNameW, std::v
294305
{
295306
commandStrings.Add(*it);
296307
}
308+
if (!encoding.empty())
309+
{
310+
commandStrings.Add(L"-mcps=CP852");
311+
}
297312
CArcCmdLineOptions options;
298313
CArcCmdLineParser parser;
299314
parser.Parse1(commandStrings, options);
@@ -328,16 +343,31 @@ LIB7ZRC MLGenericCommand(std::wstring command, std::wstring archiveNameW, std::v
328343

329344

330345
LIB7ZRC MLAddToArchive(std::wstring archiveNameW, std::vector<std::wstring> filesW, MLUpdateCallback &cb,
331-
bool encryptHeader, int compressionLevel, std::wstring workDir)
346+
bool encryptHeader, int compressionLevel, std::wstring workDir,
347+
std::wstring encoding)
332348
{
333-
return MLGenericCommand(L"a", archiveNameW, filesW, cb, encryptHeader, compressionLevel, workDir);
349+
return MLGenericCommand(L"a", archiveNameW, filesW, cb, encryptHeader, compressionLevel, workDir, encoding);
334350
}
335351

336352

337353
LIB7ZRC MLDeleteFromArchive(std::wstring archiveNameW, std::vector<std::wstring> filesW, MLUpdateCallback &cb,
338-
std::wstring workDir)
354+
std::wstring workDir, std::wstring encoding)
339355
{
340-
return MLGenericCommand(L"d", archiveNameW, filesW, cb, false, 9, workDir);
356+
return MLGenericCommand(L"d", archiveNameW, filesW, cb, false, 9, workDir, encoding);
341357
}
342358

359+
int do_one(unsigned int count, const char * const *names, void *arg) {
360+
std::vector<std::wstring> *arr = (std::vector<std::wstring> *)arg;
361+
std::wstringstream s;
362+
s << iconv_canonicalize(names[0]);
363+
arr->push_back(s.str());
364+
return 0;
365+
}
366+
367+
const std::vector<std::wstring> MLSupportedEncodings() {
368+
std::vector<std::wstring> ret;
369+
iconvlist(&do_one, &ret);
370+
return ret;
371+
}
372+
343373
}

lib7z/lib7z.h

+23-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*!
22
C++ iterface of lib7z library
33
*/
4-
// Copyright @ 2016 MPL. All rights reserved.
4+
// Copyright @ 2016-2020 MPL. All rights reserved.
55

66
#ifndef __LIB7Z_H__
77
#define __LIB7Z_H__
@@ -20,12 +20,14 @@ namespace lib7z
2020
List content of given archive file.
2121
2222
\param archiveName path to archive file
23-
\retValue output variable used to return content of archive
23+
\param retValue output variable used to return content of archive
24+
\param callbak callback object used to communicate progress and errors
25+
\param encoding file name characters encoding - blank = default
2426
\return 0 = OK, <>0 = error - one of standard errors (see Lib7zReturnCode) or user defined
2527
error returned from callback function.
2628
*/
2729
extern LIB7ZRC MLListArchive(std::wstring archiveName, std::vector<DirectoryItem> &retValue,
28-
MLListCallback &callback);
30+
MLListCallback &callback, std::wstring encoding = L"");
2931

3032
/*!
3133
Compress given set of files and/or directories into archive file.
@@ -40,12 +42,14 @@ extern LIB7ZRC MLListArchive(std::wstring archiveName, std::vector<DirectoryItem
4042
and 9 is the highest compression
4143
\param workDir directory where temporary files will be created - blank mean 'current directory'
4244
\param encryptHeader should archive header be encrypted (that encrypt file names)
45+
\param encoding file name characters encoding - blank = default
4346
\return 0 = OK, <>0 = error - one of standard errors (see Lib7zReturnCode) or user defined
4447
error returned from callback function.
4548
*/
4649
extern LIB7ZRC MLAddToArchive(std::wstring archiveName, std::vector<std::wstring> files,
47-
MLUpdateCallback &callback, bool encryptHeader = false,
48-
int compressionLevel = 9, std::wstring workDir = L"");
50+
MLUpdateCallback &callback, bool encryptHeader = false,
51+
int compressionLevel = 9, std::wstring workDir = L"",
52+
std::wstring encoding = L"");
4953

5054
/*!
5155
Extract selected files from archive or all the files and store them in given
@@ -59,11 +63,13 @@ extern LIB7ZRC MLAddToArchive(std::wstring archiveName, std::vector<std::wstring
5963
is empty, entire archive will be unpacked
6064
\param callback callback object used to communicate progress and errors
6165
\param workDir directory where temporary files will be created - blank mean 'current directory'
66+
\param encoding file name characters encoding - blank = default
6267
\return 0 = OK, <>0 = error - one of standard errors (see Lib7zReturnCode) or user defined
6368
error returned from callback function.
6469
*/
65-
extern LIB7ZRC MLExtractFromArchive(std::wstring archiveName, std::wstring outDir, std::vector<std::wstring> files,
66-
MLExtractCallback &callback, std::wstring workDir = L"");
70+
extern LIB7ZRC MLExtractFromArchive(std::wstring archiveName, std::wstring outDir,
71+
std::vector<std::wstring> files, MLExtractCallback &callback,
72+
std::wstring workDir = L"", std::wstring encoding = L"");
6773

6874
/*!
6975
Delete items from archive.
@@ -72,11 +78,20 @@ extern LIB7ZRC MLExtractFromArchive(std::wstring archiveName, std::wstring outDi
7278
\param files items to be deleted from archive - if an item is not in archive it will be ignored
7379
\param callback object used to communicate progress and errors
7480
\param workDir directory where temporary files will be created - blank mean 'current directory'
81+
\param encoding file name characters encoding - blank = default
7582
\return 0 = OK, <>0 = error - one of standard errors (see Lib7zReturnCode) or user defined
7683
error returned from callback function.
7784
*/
7885
extern LIB7ZRC MLDeleteFromArchive(std::wstring archiveName, std::vector<std::wstring> files,
79-
MLUpdateCallback &callback, std::wstring workDir = L"");
86+
MLUpdateCallback &callback, std::wstring workDir = L"",
87+
std::wstring encoding = L"");
88+
89+
90+
/*!
91+
Returns a list of supported character encodings.
92+
\return vector with supported encoding names
93+
*/
94+
extern const std::vector<std::wstring> MLSupportedEncodings();
8095

8196
}
8297

lib7z/p7zip/p7zip_src/CPP/7zip/Archive/ArjHandler.cpp

+44-3
Original file line numberDiff line numberDiff line change
@@ -583,18 +583,29 @@ HRESULT CArc::GetNextItem(CItem &item, bool &filled)
583583

584584
class CHandler:
585585
public IInArchive,
586+
public ISetProperties,
586587
public CMyUnknownImp
587588
{
588589
CObjectVector<CItem> _items;
589590
CMyComPtr<IInStream> _stream;
590591
UInt64 _phySize;
591592
CArc _arc;
593+
iconv_t _convBaseToUtf8 = (iconv_t)-1;
592594
public:
593-
MY_UNKNOWN_IMP1(IInArchive)
594-
595+
MY_QUERYINTERFACE_BEGIN2(IInArchive)
596+
MY_QUERYINTERFACE_ENTRY(ISetProperties)
597+
MY_QUERYINTERFACE_END
598+
MY_ADDREF_RELEASE
599+
595600
INTERFACE_IInArchive(;)
596601

597602
HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);
603+
~CHandler()
604+
{
605+
if (_convBaseToUtf8 != (iconv_t)-1)
606+
iconv_close(_convBaseToUtf8);
607+
}
608+
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
598609
};
599610

600611
static const Byte kArcProps[] =
@@ -703,7 +714,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
703714
const CItem &item = _items[index];
704715
switch (propID)
705716
{
706-
case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
717+
case kpidPath:
718+
prop = NItemName::GetOSName((_convBaseToUtf8 == (iconv_t)-1) ?
719+
MultiByteToUnicodeString(item.Name, CP_OEMCP) :
720+
MultiByteToUnicodeString3(item.Name, _convBaseToUtf8)); break;
707721
case kpidIsDir: prop = item.IsDir(); break;
708722
case kpidSize: prop = item.Size; break;
709723
case kpidPackSize: prop = item.PackSize; break;
@@ -965,6 +979,33 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
965979
COM_TRY_END
966980
}
967981

982+
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
983+
{
984+
for (UInt32 i = 0; i < numProps; i++)
985+
{
986+
UString name = names[i];
987+
name.MakeLower_Ascii();
988+
if (name.IsEmpty())
989+
return E_INVALIDARG;
990+
991+
const PROPVARIANT &prop = values[i];
992+
993+
if (name.IsEqualTo("cps"))
994+
{
995+
if (prop.vt == VT_BSTR)
996+
{
997+
AString codePage = UnicodeStringToMultiByte(prop.bstrVal);
998+
_convBaseToUtf8 = iconv_open("UTF-8-MAC", codePage);
999+
}
1000+
}
1001+
else
1002+
{
1003+
return E_INVALIDARG;
1004+
}
1005+
}
1006+
return S_OK;
1007+
}
1008+
9681009
static const Byte k_Signature[] = { kSig0, kSig1 };
9691010

9701011
REGISTER_ARC_I(

lib7z/p7zip/p7zip_src/CPP/7zip/Archive/LzhHandler.cpp

+49-2
Original file line numberDiff line numberDiff line change
@@ -453,17 +453,29 @@ struct CItemEx: public CItem
453453

454454
class CHandler:
455455
public IInArchive,
456+
public ISetProperties,
456457
public CMyUnknownImp
457458
{
458459
CObjectVector<CItemEx> _items;
459460
CMyComPtr<IInStream> _stream;
460461
UInt64 _phySize;
461462
UInt32 _errorFlags;
462463
bool _isArc;
464+
iconv_t _convBaseToUtf8 = (iconv_t)-1;
463465
public:
464-
MY_UNKNOWN_IMP1(IInArchive)
466+
MY_QUERYINTERFACE_BEGIN2(IInArchive)
467+
MY_QUERYINTERFACE_ENTRY(ISetProperties)
468+
MY_QUERYINTERFACE_END
469+
MY_ADDREF_RELEASE
470+
465471
INTERFACE_IInArchive(;)
466472
CHandler();
473+
~CHandler()
474+
{
475+
if (_convBaseToUtf8 != (iconv_t)-1)
476+
iconv_close(_convBaseToUtf8);
477+
}
478+
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
467479
};
468480

469481
IMP_IInArchive_Props
@@ -503,7 +515,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
503515
{
504516
case kpidPath:
505517
{
506-
UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
518+
UString s;
519+
if (_convBaseToUtf8 == (iconv_t)-1)
520+
{
521+
s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
522+
}
523+
else
524+
{
525+
s = NItemName::WinNameToOSName(MultiByteToUnicodeString3(item.GetName(), _convBaseToUtf8));
526+
}
507527
if (!s.IsEmpty())
508528
{
509529
if (s.Back() == WCHAR_PATH_SEPARATOR)
@@ -776,6 +796,33 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
776796
COM_TRY_END
777797
}
778798

799+
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
800+
{
801+
for (UInt32 i = 0; i < numProps; i++)
802+
{
803+
UString name = names[i];
804+
name.MakeLower_Ascii();
805+
if (name.IsEmpty())
806+
return E_INVALIDARG;
807+
808+
const PROPVARIANT &prop = values[i];
809+
810+
if (name.IsEqualTo("cps"))
811+
{
812+
if (prop.vt == VT_BSTR)
813+
{
814+
AString codePage = UnicodeStringToMultiByte(prop.bstrVal);
815+
_convBaseToUtf8 = iconv_open("UTF-8-MAC", codePage);
816+
}
817+
}
818+
else
819+
{
820+
return E_INVALIDARG;
821+
}
822+
}
823+
return S_OK;
824+
}
825+
779826
static const Byte k_Signature[] = { '-', 'l', 'h' };
780827

781828
REGISTER_ARC_I(

0 commit comments

Comments
 (0)