libzip: zip_name_locate() 在特定文件名上失败,甚至尝试了所有可能的编码组合
libzip: zip_name_locate() fails on specific filename, even trying all possible encoding combinations
我正在尝试在 libzip 之上构建一个“故障安全”层,但 libzip 在这里给我带来了一些麻烦。
首先,我使用 zip_file_add(...)
将一个文件添加到我的(空)存档中。这有 3 种可能的用户定义编码可用。然后我尝试使用 zip_name_locate(...)
找到名称,它也有 3 种可能的用户定义编码可用。
此 mcve 检查所有可能的编码组合,但对于特定文件名 x%²»Ã-ØÑ–6¨wx.txt
,所有组合均失败。当使用更传统的 file.txt
文件名时,zip_name_locate()
每次都会成功。
#include <zip.h>
#include <include/libzip.h>//<.pragmas to include the .lib's...
#include <iostream>
#include <vector>
#include <utility>
/*
'zip_file_add' possible encodings:
ZIP_FL_ENC_GUESS
ZIP_FL_ENC_UTF_8
ZIP_FL_ENC_CP437
'zip_name_locate' possible encodings:
ZIP_FL_ENC_RAW
ZIP_FL_ENC_GUESS
ZIP_FL_ENC_STRICT
*/
/*
build encoding pairs (trying all possibilities)
*/
std::vector<std::pair<unsigned, unsigned>>
encoding_pairs{
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_STRICT },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_STRICT },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_STRICT },
};
int main(int argc, char** argv) {
const char* file_buf = "hello world";
#if 0
const char* file_name = "file.txt";
#else
const char* file_name = "x%²»Ã-ØÑ–6¨wx.txt";
#endif
zip_error_t ze;
zip_error_init(&ze);
{
zip_source_t* zs = zip_source_buffer_create(nullptr, 0, 1, &ze);
if (zs == NULL)
return -1;
zip_t* z = zip_open_from_source(zs, ZIP_CHECKCONS, &ze);
if (z == NULL)
return -1;
{
zip_source_t* s = zip_source_buffer(z, file_buf, strlen(file_buf), 0);//0 = don't let libzip auto-free the const char* buffer on the stack
if (s == NULL)
return -1;
for (size_t ep = 0; ep < encoding_pairs.size(); ep++) {
std::cout << "ep = " << ep << std::endl;
zip_uint64_t index;
if ((index = zip_file_add(z, file_name, s, encoding_pairs[ep].first)) == -1) {
std::cout << "could not zip_file_add() with encoding " << encoding_pairs[ep].first << std::endl;
continue;
}
if (zip_name_locate(z, file_name, encoding_pairs[ep].second) == -1) {
std::cout << "the name '" << file_name << "' could not be located." << std::endl;
std::cout << " encoding pair: " << encoding_pairs[ep].first << " <-> " << encoding_pairs[ep].second << std::endl;
}
else {
std::cout << "the name was located." << std::endl;
}
if (zip_delete(z, index) == -1)
return -1;
}
}
zip_close(z);
}
zip_error_fini(&ze);
return 0;
}
我不明白我在这里做错了什么,或者 libzip 甚至无法解析这样的名称。
如果不能,那么要避免的名称标准是什么?
原来问题出在我的源文件本身的编码上。它是 ANSI - 所以我将它转换为 UTF8 并解决了问题。
我仍然不明白的是为什么 libzip 不能 zip_name_locate()
来自输入 c-string 的名称与 [=] 中使用的输入 c-string 完全相同11=](无论源文件编码是什么)。也许是“迷失在翻译中”?
(特别感谢 Thomas Klausner 帮我找到问题)
我正在尝试在 libzip 之上构建一个“故障安全”层,但 libzip 在这里给我带来了一些麻烦。
首先,我使用 zip_file_add(...)
将一个文件添加到我的(空)存档中。这有 3 种可能的用户定义编码可用。然后我尝试使用 zip_name_locate(...)
找到名称,它也有 3 种可能的用户定义编码可用。
此 mcve 检查所有可能的编码组合,但对于特定文件名 x%²»Ã-ØÑ–6¨wx.txt
,所有组合均失败。当使用更传统的 file.txt
文件名时,zip_name_locate()
每次都会成功。
#include <zip.h>
#include <include/libzip.h>//<.pragmas to include the .lib's...
#include <iostream>
#include <vector>
#include <utility>
/*
'zip_file_add' possible encodings:
ZIP_FL_ENC_GUESS
ZIP_FL_ENC_UTF_8
ZIP_FL_ENC_CP437
'zip_name_locate' possible encodings:
ZIP_FL_ENC_RAW
ZIP_FL_ENC_GUESS
ZIP_FL_ENC_STRICT
*/
/*
build encoding pairs (trying all possibilities)
*/
std::vector<std::pair<unsigned, unsigned>>
encoding_pairs{
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_STRICT },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_STRICT },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_STRICT },
};
int main(int argc, char** argv) {
const char* file_buf = "hello world";
#if 0
const char* file_name = "file.txt";
#else
const char* file_name = "x%²»Ã-ØÑ–6¨wx.txt";
#endif
zip_error_t ze;
zip_error_init(&ze);
{
zip_source_t* zs = zip_source_buffer_create(nullptr, 0, 1, &ze);
if (zs == NULL)
return -1;
zip_t* z = zip_open_from_source(zs, ZIP_CHECKCONS, &ze);
if (z == NULL)
return -1;
{
zip_source_t* s = zip_source_buffer(z, file_buf, strlen(file_buf), 0);//0 = don't let libzip auto-free the const char* buffer on the stack
if (s == NULL)
return -1;
for (size_t ep = 0; ep < encoding_pairs.size(); ep++) {
std::cout << "ep = " << ep << std::endl;
zip_uint64_t index;
if ((index = zip_file_add(z, file_name, s, encoding_pairs[ep].first)) == -1) {
std::cout << "could not zip_file_add() with encoding " << encoding_pairs[ep].first << std::endl;
continue;
}
if (zip_name_locate(z, file_name, encoding_pairs[ep].second) == -1) {
std::cout << "the name '" << file_name << "' could not be located." << std::endl;
std::cout << " encoding pair: " << encoding_pairs[ep].first << " <-> " << encoding_pairs[ep].second << std::endl;
}
else {
std::cout << "the name was located." << std::endl;
}
if (zip_delete(z, index) == -1)
return -1;
}
}
zip_close(z);
}
zip_error_fini(&ze);
return 0;
}
我不明白我在这里做错了什么,或者 libzip 甚至无法解析这样的名称。
如果不能,那么要避免的名称标准是什么?
原来问题出在我的源文件本身的编码上。它是 ANSI - 所以我将它转换为 UTF8 并解决了问题。
我仍然不明白的是为什么 libzip 不能 zip_name_locate()
来自输入 c-string 的名称与 [=] 中使用的输入 c-string 完全相同11=](无论源文件编码是什么)。也许是“迷失在翻译中”?
(特别感谢 Thomas Klausner 帮我找到问题)