mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
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:
parent
d6e26401ca
commit
d087a7db42
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
int open = zipOpenNewFileInZip(m_ZipFile, zipPathAscii.c_str(), nullptr, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
|
||||
if (open != ZIP_OK)
|
||||
if (zipPathUTF8[i] == '\\')
|
||||
{
|
||||
zipPathUTF8[i] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -121,6 +121,7 @@ private:
|
||||
|
||||
HANDLE m_PackagerThread;
|
||||
zipFile m_ZipFile;
|
||||
bool m_AllowNonAsciiFilenames;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
Loading…
Reference in New Issue
Block a user