reactos/dll/shellext/zipfldr/CZipEnumerator.hpp
Katayama Hirofumi MZ 104ef25fcc
[ZIPFLDR][BOOTDATA] Support UTF-8 Zip packing (#5450)
New ReactOS can zip/unzip files and folders in UTF-8 filenames.
You can also choose the codepage of filenames to zip/unzip via
the ZipCodePage / UnZipCodePage registry values on the registry
key HKEY_CURRENT_USER\Software\ReactOS.

Windows 8 or later also support UTF-8 zipped folders.
You can also use 3rd party software to zip/unzip in older Windows.

- Use <atlconv.h> for string conversion.
- Use zipOpenNewFileInZip4_64 instead of zipOpenNewFileInZip3_64,
  and then add MINIZIP_UTF8_FLAG flag.
- Set the filenames in UTF-8 by using CP_UTF8 codepage.
- Codepage is user selectable via registry settings.

CORE-16668
2023-07-22 12:57:32 +09:00

105 lines
2.7 KiB
C++

/*
* PROJECT: ReactOS Zip Shell Extension
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: CZipEnumerator
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
struct CZipEnumerator
{
private:
CComPtr<IZip> m_Zip;
bool m_First;
CAtlList<CStringW> m_Returned;
UINT m_nCodePage;
public:
CZipEnumerator()
: m_First(true)
, m_nCodePage(GetZipCodePage(TRUE))
{
}
bool initialize(IZip* zip)
{
m_Zip = zip;
return reset();
}
bool reset()
{
unzFile uf = m_Zip->getZip();
m_First = true;
if (unzGoToFirstFile(uf) != UNZ_OK)
return false;
m_Returned.RemoveAll();
return true;
}
bool next_unique(PCWSTR prefix, CStringW& name, bool& folder, unz_file_info64& info)
{
size_t len = wcslen(prefix);
CStringW tmp;
while (next(tmp, info))
{
if (!_wcsnicmp(tmp, prefix, len))
{
int pos = tmp.Find(L'/', len);
if (pos < 0)
{
name = tmp.Mid(len);
folder = false;
}
else
{
name = tmp.Mid(len, pos - len);
folder = true;
}
tmp = name;
tmp.MakeLower();
POSITION it = m_Returned.Find(tmp);
if (!name.IsEmpty() && !it)
{
m_Returned.AddTail(tmp);
return true;
}
}
}
return false;
}
bool next(CStringW& name, unz_file_info64& info)
{
int err;
unzFile uf = m_Zip->getZip();
if (!m_First)
{
err = unzGoToNextFile(uf);
if (err == UNZ_END_OF_LIST_OF_FILE)
{
return false;
}
}
m_First = false;
err = unzGetCurrentFileInfo64(uf, &info, NULL, 0, NULL, 0, NULL, 0);
if (err == UNZ_OK)
{
CStringA nameA;
PSTR buf = nameA.GetBuffer(info.size_filename);
err = unzGetCurrentFileInfo64(uf, NULL, buf, nameA.GetAllocLength(), NULL, 0, NULL, 0);
nameA.ReleaseBuffer(info.size_filename);
nameA.Replace('\\', '/');
if (info.flag & MINIZIP_UTF8_FLAG)
name = CA2WEX<MAX_PATH>(nameA, CP_UTF8);
else
name = CA2WEX<MAX_PATH>(nameA, m_nCodePage);
}
return err == UNZ_OK;
}
};