2022-08-13 01:29:00 +00:00
|
|
|
#include "scanner_setting.h"
|
|
|
|
#include <time.h>
|
2022-08-13 02:37:00 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2022-08-13 01:29:00 +00:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// 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;
|
|
|
|
}
|