SkinInstaller/SkinPackager: Fix Unicode filename handling

Existing .rmskin files need to be repackaged for proper Unicode filename support.

Non-ASCII filenames can be used only if 'Minimum Rainmeter' is set to at least '3.0.1'. An error will be displayed otherwise.
This commit is contained in:
Birunthan Mohanathas 2013-10-16 17:21:07 +03:00
parent d6e26401ca
commit d087a7db42
5 changed files with 46 additions and 13 deletions

View File

@ -405,11 +405,14 @@ bool DialogInstall::ReadPackage()
// Helper to sets buffer with current file name
auto getFileInfo = [&]()->bool
{
char cBuffer[MAX_PATH];
char cBuffer[MAX_PATH * 3];
unz_file_info ufi;
if (unzGetCurrentFileInfo(m_PackageUnzFile, &ufi, cBuffer, MAX_PATH, nullptr, 0, nullptr, 0) == UNZ_OK)
if (unzGetCurrentFileInfo(
m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK)
{
MultiByteToWideChar(CP_ACP, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH);
const uLong ZIP_UTF8_FLAG = 1 << 11;
const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP;
MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH);
while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\';
return true;
}
@ -713,11 +716,14 @@ bool DialogInstall::InstallPackage()
// Helper to sets buffer with current file name
auto getFileInfo = [&]()->bool
{
char cBuffer[MAX_PATH];
char cBuffer[MAX_PATH * 3];
unz_file_info ufi;
if (unzGetCurrentFileInfo(m_PackageUnzFile, &ufi, cBuffer, MAX_PATH, nullptr, 0, nullptr, 0) == UNZ_OK)
if (unzGetCurrentFileInfo(
m_PackageUnzFile, &ufi, cBuffer, _countof(cBuffer), nullptr, 0, nullptr, 0) == UNZ_OK)
{
MultiByteToWideChar(CP_ACP, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH);
const uLong ZIP_UTF8_FLAG = 1 << 11;
const DWORD codePage = (ufi.flag & ZIP_UTF8_FLAG) ? CP_UTF8 : CP_ACP;
MultiByteToWideChar(codePage, 0, cBuffer, strlen(cBuffer) + 1, buffer, MAX_PATH);
while (WCHAR* pos = wcschr(buffer, L'/')) *pos = L'\\';
return true;
}

View File

@ -17,6 +17,7 @@
*/
#include "StdAfx.h"
#include "../Common/StringUtil.h"
#include "Application.h"
#include "DialogPackage.h"
#include "DialogInstall.h"
@ -37,7 +38,8 @@ DialogPackage::DialogPackage(HWND wnd) : Dialog(wnd),
m_LoadLayout(false),
m_MergeSkins(false),
m_PackagerThread(),
m_ZipFile()
m_ZipFile(),
m_AllowNonAsciiFilenames(false)
{
}
@ -263,12 +265,16 @@ bool DialogPackage::CreatePackage()
WritePrivateProfileString(L"rmskin", L"MinimumRainmeter", m_MinimumRainmeter.c_str(), tempFile);
WritePrivateProfileString(L"rmskin", L"MinimumWindows", m_MinimumWindows.c_str(), tempFile);
// Only Skin Installer in Rainmeter 3.0.1 support UTF-8 filenames.
m_AllowNonAsciiFilenames = DialogInstall::CompareVersions(m_MinimumRainmeter, L"3.0.1") != -1;
// Create archive and add options file and header bitmap
m_ZipFile = zipOpen(ConvertToAscii(m_TargetFile.c_str()).c_str(), APPEND_STATUS_CREATE);
auto cleanup = [&]()->bool
{
zipClose(m_ZipFile, nullptr);
DeleteFile(m_TargetFile.c_str());
return false;
};
@ -379,17 +385,30 @@ unsigned __stdcall DialogPackage::PackagerThreadProc(void* pParam)
bool DialogPackage::AddFileToPackage(const WCHAR* filePath, const WCHAR* zipPath)
{
std::string zipPathAscii = ConvertToAscii(zipPath);
for (int i = 0, isize = zipPathAscii.length(); i < isize; ++i)
std::string zipPathUTF8 = StringUtil::NarrowUTF8(zipPath);
for (int i = 0, isize = zipPathUTF8.length(); i < isize; ++i)
{
if (zipPathAscii[i] == '\\')
if ((zipPathUTF8[i] & 0x80) != 0)
{
zipPathAscii[i] = '/';
// UTF-8 lead bit is not zero so the string is non-ASCII.
if (!m_AllowNonAsciiFilenames)
{
return false;
}
}
if (zipPathUTF8[i] == '\\')
{
zipPathUTF8[i] = '/';
}
}
int open = zipOpenNewFileInZip(m_ZipFile, zipPathAscii.c_str(), nullptr, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
if (open != ZIP_OK)
const uLong ZIP_UTF8_FLAG = 1 << 11;
zip_fileinfo fi = {0};
if (zipOpenNewFileInZip4(
m_ZipFile, zipPathUTF8.c_str(), &fi,
nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION,
0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, 0, ZIP_UTF8_FLAG) != ZIP_OK)
{
return false;
}

View File

@ -121,6 +121,7 @@ private:
HANDLE m_PackagerThread;
zipFile m_ZipFile;
bool m_AllowNonAsciiFilenames;
};
#endif

View File

@ -122,6 +122,7 @@
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\StringUtil.cpp" />
<ClCompile Include="..\Library\Dialog.cpp" />
<ClCompile Include="Application.cpp" />
<ClCompile Include="DialogInstall.cpp" />

View File

@ -19,6 +19,9 @@
<Filter Include="zlib\minizip">
<UniqueIdentifier>{b726e25d-2977-424a-b45b-8ee60ce6bd49}</UniqueIdentifier>
</Filter>
<Filter Include="Common">
<UniqueIdentifier>{b69ece81-b900-41d8-9ccd-61476261c411}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Application.cpp">
@ -81,6 +84,9 @@
<ClCompile Include="DialogPackage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Common\StringUtil.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">