code_device/hgdriver/hgdev/scanner_setting.cpp

322 lines
7.3 KiB
C++
Raw Normal View History

#include "scanner_setting.h"
#include <time.h>
2022-08-13 02:37:00 +00:00
#include <stdio.h>
#include <string.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEFINE ...
#define SSFH_VER_MAIN 1
#define SSFH_VER_MINOR 0
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// base64 util ..
static char base64_default_table[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" };
base64::base64() : padding_char_('=')
{
base64_ind_[0] = base64_char_[0] = 0;
initialize_base64_table(base64_default_table);
}
base64::~base64()
{}
bool base64::is_valid_base64_table(const char* table)
{
bool valid = false;
if (table && strlen(table) >= 64)
{
char repeat[4] = { 0 };
valid = true;
for (int i = 0; i < 63; ++i)
{
repeat[0] = table[i];
if (strstr(table + i + 1, repeat))
{
valid = false;
break;
}
}
}
return valid;
}
bool base64::initialize_base64_table(const char* table)
{
if (!table || strlen(table) < 64)
{
if (memcmp(base64_default_table, base64_char_, 64) == 0)
{
return !table;
}
memcpy(base64_char_, base64_default_table, 64);
}
else
{
if (memcmp(base64_char_, table, 64) == 0)
{
return true;
}
else if (!is_valid_base64_table(table))
return false;
memcpy(base64_char_, table, 64);
}
base64_char_[64] = base64_char_[65] = 0;
// initialize base64_index
memset(base64_ind_, 0, sizeof(base64_ind_));
for (int i = 0; i < 64; ++i)
{
base64_ind_[base64_char_[i]] = i;
}
// padding char
padding_char_ = '=';
if (base64_ind_[padding_char_])
{
for (padding_char_ = 0x21; padding_char_ < 0x7e && base64_ind_[padding_char_] && padding_char_ != base64_char_[0]; ++padding_char_);
}
return padding_char_ < 0x7e;
}
bool base64::set_base64_table(const char* table)
{
return initialize_base64_table(table ? table : base64_default_table);
}
std::string base64::encode(const char* data, size_t bytes, unsigned int line_bytes, bool need_padding)
{
char* str = (char*)malloc(bytes * 2 + 3);
unsigned char c1 = 0, c2 = 0, c3 = 0;
unsigned long line_len = 0;
unsigned long words = bytes / 3;
int rest = bytes % 3,
pos = 0;
std::string ret("");
for (unsigned long i = 0; i < words; ++i)
{
// fetch 3 letters
c1 = *data++;
c2 = *data++;
c3 = *data++;
// encoding into 4-bytes
str[pos++] = base64_char_[c1 >> 2];
str[pos++] = base64_char_[((c1 << 4) | (c2 >> 4)) & 0x3f];
str[pos++] = base64_char_[((c2 << 2) | (c3 >> 6)) & 0x3f];
str[pos++] = base64_char_[c3 & 0x3f];
line_len += 4;
// new line ...
if ((unsigned int)line_len > line_bytes - 4)
{
str[pos++] = '\r';
str[pos++] = '\n';
line_len = 0;
}
}
// rest ...
if (rest == 1)
{
c1 = *data++;
str[pos++] = base64_char_[(c1 & 0xfc) >> 2];
str[pos++] = base64_char_[((c1 & 0x03) << 4)];
if (need_padding)
{
str[pos++] = padding_char_;
str[pos++] = padding_char_;
}
}
else if (rest == 2)
{
c1 = *data++;
c2 = *data++;
str[pos++] = base64_char_[(c1 & 0xfc) >> 2];
str[pos++] = base64_char_[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
str[pos++] = base64_char_[((c2 & 0x0f) << 2)];
if (need_padding)
{
str[pos++] = padding_char_;
}
}
if (pos > 0)
{
str[pos++] = 0;
ret = std::string(str, pos - 1);
}
free(str);
return ret;
}
std::string base64::decode(const char* data, size_t bytes)
{
char* str = (char*)malloc(bytes + 1);
int pos = 0,
shifts = 18,
value = 0;
std::string ret("");
for (int i = 0; i < (int)bytes; ++i)
{
if (*data != '\r' && *data != '\n')
{
if (*data == padding_char_)
{
break;
}
value += base64_ind_[*data] << shifts;
if (shifts == 0)
{
shifts = 18;
str[pos++] = (value >> 16) & 0x0ff;
str[pos++] = (value >> 8) & 0x0ff;
str[pos++] = (value >> 0) & 0x0ff;
value = 0;
}
else
{
shifts -= 6;
}
}
data++;
}
if (shifts == 12 || shifts == 6)
{
str[pos++] = (value >> 16) & 0x0ff;
}
else if (shifts == 0)
{
str[pos++] = (value >> 16) & 0x0ff;
str[pos++] = (value >> 8) & 0x0ff;
}
if (pos > 0)
{
str[pos++] = 0;
ret = std::string(str, pos - 1);
}
free(str);
return ret;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// check sum ..
unsigned int simple_checksum(const char* data, size_t len)
{
unsigned int chk = -1;
while (len >= sizeof(chk))
{
chk ^= *((unsigned int*)data);
data += sizeof(chk);
len -= sizeof(chk);
}
if (len)
{
unsigned int rest = *((unsigned int*)data), mask = (1 << (len * 8)) - 1;
rest &= mask;
chk ^= rest;
}
return chk;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// exporting ..
int load_scanner_setting(const char* file, std::string& jsn)
{
FILE* src = fopen(file, "rb");
long len = 0;
char* buf = nullptr;
SSFILEH ssfh = { 0 };
if (!src)
return errno;
fseek(src, 0, SEEK_END);
len = ftell(src);
fseek(src, 0, SEEK_SET);
if (len < sizeof(ssfh))
{
fclose(src);
return EBADF;
}
buf = new char[len];
if (!buf)
{
fclose(src);
return ENOMEM;
}
memset(buf, 0, len);
fread(&ssfh, sizeof(ssfh), 1, src);
len -= sizeof(ssfh);
fread(buf, 1, len, src);
fclose(src);
if (ssfh.ver_main != 1 ||
ssfh.ver_sub != 0 ||
simple_checksum(buf, len) != (ssfh.checksum ^ ssfh.timestamp) ||
ssfh.length != len + sizeof(ssfh))
{
delete[] buf;
return EBADF;
}
base64 b64;
jsn = b64.decode(buf, len);
delete[] buf;
return 0;
}
int save_scanner_setting(const char* file, const std::string& jsn)
{
SSFILEH ssfh = { 0 };
base64 b64;
std::string str(b64.encode(jsn.c_str(), jsn.length()));
ssfh.ver_main = SSFH_VER_MAIN;
ssfh.ver_sub = SSFH_VER_MINOR;
ssfh.length = str.length() + sizeof(ssfh);
ssfh.timestamp = time(NULL);
ssfh.checksum = simple_checksum(str.c_str(), str.length());
FILE *dst = fopen(file, "wb");
bool ok = false;
if (!dst)
return ENFILE;
ssfh.checksum ^= ssfh.timestamp;
if (fwrite(&ssfh, sizeof(ssfh), 1, dst) == 1)
ok = fwrite(str.c_str(), 1, str.length(), dst) == str.length();
fclose(dst);
if (!ok)
{
remove(file);
return EFAULT;
}
return 0;
}