Мне нужно декодировать шестнадцатеричные строки, хранящиеся в формате zlib. Пример:
1800000013000000eAFjYoAAZiDFCMQgGgQAAJwACg ==
, где 18000000 и 13000000 - размер несжатых / сжатых данных (в данном случае 24 и 19).
Также я знаю, что остальная часть строки содержит
020000000000000003000000010000000300000000000000
Где проблема? после любого урока, например https://panthema.net/2007/0328-ZLibString.html сжатие этой строки, я получаю
х? 302 @? P ??
что в шестнадцатеричном виде можно записать как
783f3330324053f503f103ff5
Это не имеет ничего общего с моей ожидаемой сжатой строкой, поэтому я не нашел способа распаковать исходную строку (это моя конечная цель)
Заранее благодарю за любой совет!
PS. Я использую распаковку из
https://github.com/systemed/intersector/blob/master/helpers.cpp
Похоже, что строка была закодирована в base64 (спасибо @zdenek и @ Mark-Adler) Мне удалось расшифровать ее с помощью
BYTE *res;
int resSize = FromBase64Simple((BYTE*)actualData.c_str(),actualData.len(),res,sizeCompressed);
Вы можете прочитать реализацию из https://github.com/kengonakajima/luvit-base64/blob/master/base64.c
Но это не проблема, так как я могу вывести результат, используя
char* resChar = new char[resSize];
for(int i = 0;i<resSize;i++)
{
int asciiCode = (BYTE)res[i];
resChar[i]=char(asciiCode);
char buffer [2];
itoa (asciiCode,buffer,16);
qDebug()<<"["<<i<<"]\t"<<asciiCode<<"\t"<<buffer;
}
Я получаю результат каждого байта в десятичном и шестнадцатеричном виде, и оба в порядке. Шестнадцатеричный выглядит как:
78 01 63 62 80 00 66 20 c5 08 c4 20 1a 04 00 00 9c 00 0a
Но resChar - это "x? Cb?" это не имеет ничего общего со значением, сказанным @ Mark-Adler "x? 302 @? P ??" (где очевидно символы «?» не для печати), я действительно думаю, что здесь проблема, но мои данные, кажется, соответствуют этой таблице: https://www.asciitable.com/, а у Марка также нет этой сети https://conv.darkbyte.ru/ возвращает те же результаты, что и мой алгоритм
Я пытался распаковать строку, используя реализацию, указанную выше, но это не удалось (также попытался https://gist.github.com/arq5x/5315739), но его распакованное значение представляет собой строку из одного символа ""
Здесь мы рассмотрим минимальный воспроизводимый случай:
#include <string>
static char LookupDigits[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //gap: ctrl chars
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //gap: ctrl chars
0,0,0,0,0,0,0,0,0,0,0, //gap: spc,!"#$%'()*
62, // +
0, 0, 0, // gap ,-.
63, // /
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // 0-9
0, 0, 0, // gap: :;<
99, // = (end padding)
0, 0, 0, // gap: >?@
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25, // A-Z
0, 0, 0, 0, 0, 0, // gap: [\]^_`
26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,
43,44,45,46,47,48,49,50,51, // a-z
0, 0, 0, 0, // gap: {|}~ (and the rest...)
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
int FromBase64Simple(const unsigned char* pSrc, int nLenSrc, unsigned char* pDst, int nLenDst)
{
int nLenOut = 0;
for (int j = 0; j<nLenSrc; j += 4) {
if (nLenOut > nLenDst) {
return(0); // error, buffer too small
}
unsigned char s1 = LookupDigits[*pSrc++];
unsigned char s2 = LookupDigits[*pSrc++];
unsigned char s3 = LookupDigits[*pSrc++];
unsigned char s4 = LookupDigits[*pSrc++];
unsigned char d1 = ((s1 & 0x3f) << 2) | ((s2 & 0x30) >> 4);
unsigned char d2 = ((s2 & 0x0f) << 4) | ((s3 & 0x3c) >> 2);
unsigned char d3 = ((s3 & 0x03) << 6) | ((s4 & 0x3f) >> 0);
*pDst++ = d1; nLenOut++;
if (s3 == 99) break; // end padding found
*pDst++ = d2; nLenOut++;
if (s4 == 99) break; // end padding found
*pDst++ = d3; nLenOut++;
}
return(nLenOut);
}
int main()
{
std::string inputData = "eAFjYoAAZiDFCMQgGgQAAJwACg==";
//19 is hardcoded since I know its size prior to this call
unsigned char res[19];
int resSize = FromBase64Simple((unsigned char*)inputData.c_str(), inputData.size(), res, 19);
for (int i = 0; i<resSize; i++)
{
int asciiCode = res[i];
printf("[%i]\t%i\t%x\n", i, asciiCode, asciiCode);
}
printf("\n\nres: %s", (char*)res);
getchar();
return 0;
}