campo-sirio/include/dongle.cpp
guy 7040da8224 Patch level : 10.0
Files correlati     : ba0.exe
Ricompilazione Demo : [ ]
Commento            :
Aggiunta riga definizione modulo Hardy
#define HAAUT 46


git-svn-id: svn://10.65.10.50/branches/R_10_00@20893 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-09-22 09:39:46 +00:00

1377 lines
32 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <xvt.h>
#include <applicat.h>
#include <config.h>
#include <dongle.h>
#include <isamrpc.h>
#include <modaut.h>
#include <scanner.h>
#include <utility.h>
#include <xvtility.h>
#include <urldefid.h>
///////////////////////////////////////////////////////////
// Dongle stuff
///////////////////////////////////////////////////////////
#define USERADR 26952
#define AGAADR 26953
#define REFKEY (unsigned char*)"CAMPOKEY"
#define VERKEY (unsigned char*)"ìpÙˆ¬cê<"
#pragma pack(push, 1)
struct TEutronHeader
{
char _serno[8]; // 8
unsigned short _year_assist; // 10
unsigned short _max_users; // 12
unsigned long _last_date; // 16
unsigned long _scad_date; // 20
unsigned long _checksum; // 24
unsigned short _version; // 26
unsigned short _patch; // 28
unsigned short _offset_to_bits; // 30
unsigned short _size_of_bits; // 32
};
struct TEutronFooter
{
unsigned long _size; // Should be sizeof(TEutronFooter)
unsigned long _checksum; // Much smarter position than header
unsigned long _filler1;
unsigned long _filler2;
unsigned long _filler3;
unsigned long _filler4;
unsigned long _filler5;
unsigned long _last_assist; // Last date of assistance query
unsigned long _assistance[MAX_DONGLE_ASSIST]; // Pre-payed assistance
unsigned long checksum(bool set);
bool valid();
TEutronFooter();
};
#pragma pack(pop)
TEutronFooter::TEutronFooter()
{
const int s = sizeof(TEutronFooter);
memset(&_size, 0, s);
_size = s;
}
unsigned long TEutronFooter::checksum(bool set)
{
if (set) _size = sizeof(TEutronFooter);
const word offset = sizeof(_size) + sizeof(_checksum);
byte* ptr = (byte*)(&_size) + offset;
const word len = word(_size - offset);
unsigned long cs = 0;
for (word i = 0; i < len; i++, ptr++)
cs += *ptr | ~(short(*ptr << 8));
if (set) _checksum = cs;
return cs;
}
bool TEutronFooter::valid()
{
if (_size == 0 || _checksum == 0)
return false;
return _checksum == checksum(false);
}
///////////////////////////////////////////////////////////
// Current dongle
///////////////////////////////////////////////////////////
static TDongle* _dongle = NULL;
TDongle& dongle()
{
if (_dongle == NULL)
_dongle = new TDongle;
return *_dongle;
}
bool destroy_dongle()
{
bool ok = _dongle != NULL;
if (ok)
{
delete _dongle;
_dongle = NULL;
}
return ok;
}
///////////////////////////////////////////////////////////
// Bit helper functions
///////////////////////////////////////////////////////////
inline bool test_bit(word w, int b)
{
bool on = (w & (1 << b)) != 0;
return on;
}
inline void set_bit(word& w, int b, bool on = true)
{
if (on)
w |= 1 << b;
else
w &= ~(1 << b);
}
inline void reset_bit(word& w, byte b)
{
w &= ~(1 << b);
}
///////////////////////////////////////////////////////////
// TDongle
///////////////////////////////////////////////////////////
TDongle::TDongle()
: _hardware(_dongle_unknown), _type(_no_dongle), _serno(0xFFFF),
_max_users(1), _year_assist(2009), _dirty(false), _OEM(-1)
{
memset(_eprom, 0, sizeof(_eprom));
memset(_assist, 0, sizeof(_assist));
}
TDongle::~TDongle()
{
if (_serno != 0xFFFF)
logout();
}
const TString& TDongle::administrator(TString* pwd) const
{
if (_admin.blank())
oem();
if (pwd)
*pwd = _admpwd;
return _admin;
}
// Data punta ad un array di 4 words
// Deve essere cosi' per problemi del C,
// non trasformare in array: pena di morte!
void TDongle::garble(word* data) const
{
switch (_hardware)
{
case _dongle_hardlock:
xvt_dongle_hl_crypt(data);
break;
case _dongle_eutron:
xvt_dongle_sl_crypt(data);
break;
default:
break;
}
}
bool TDongle::already_programmed() const
{
if (_hardware == _dongle_hardlock)
{
word data[4];
memcpy(data, &_eprom[60], sizeof(data));
garble(data);
if (data[0] < 1997 || data[0] > 2997)
return false;
if (data[1] == 0 || data[1] >= 10000)
return false;
const TDate today(TODAY);
const long giulio = *((const long*)&data[2]);
const long yyyymmdd = today.julian2date(giulio);
const TDate d(yyyymmdd);
if (d.year() < 1997 || d > today)
return false;
} else
if (_hardware == _dongle_eutron)
{
const TEutronHeader* eh = (const TEutronHeader*)_eprom;
if (eh->_serno[0] == 0 || eh->_checksum == 0)
return false; // Really virgin.
unsigned long cs = 0;
for (byte* ptr = (byte*)_eprom; ptr < (byte*)&eh->_checksum; ptr++)
cs += *ptr | ~(short(*ptr << 8));
if (eh->_checksum != cs)
return false; // Malicious programming!
}
return true;
}
void TDongle::set_developer_permissions()
{
if (_serno == 0 && is_power_station())
{
_module.set(255); // Last module on key
_module.set(); // Activate all modules
}
else
{
_module.reset(-1);
_module.set(0, true);
}
_shown.reset();
_max_users = 1;
_last_update = TDate(TODAY);
_year_assist = 3000;
}
bool TDongle::hardlock_login(bool test_all_keys)
{
bool ok = true;
_type = _user_dongle;
if (test_all_keys)
{
xvt_dongle_hl_logout();
if (xvt_dongle_hl_login(AGAADR, REFKEY, VERKEY))
_type = _aga_dongle;
}
xvt_dongle_hl_logout();
ok = xvt_dongle_hl_login(USERADR, REFKEY, VERKEY) != 0;
if (ok)
{
_hardware = _dongle_hardlock;
xvt_dongle_hl_read_block((unsigned char*)_eprom);
word data[4];
memcpy(data, _eprom, sizeof(data));
garble(data);
if (data[0] == 0xFAE8)
_serno = data[1];
else
{
if (data[0] == 0x3283 || data[0] == 0xA3AA) // chiave programmatori !!
{
if (_type == _user_dongle)
_type = _developer_dongle;
_serno = 0;
#ifdef DBG
if (test_all_keys && is_power_station())
_type = _aga_dongle;
#endif
}
}
}
if (ok)
{
_max_users = 1;
_last_update = TDate(TODAY);
_year_assist = _last_update.year();
if (_type == _user_dongle) //chiave cliente
{
const bool already = already_programmed();
_module.reset(); // Disattiva tutti i moduli
_shown.reset();
const int last_word = already ? 12 : 4;
word data[4];
// Legge flag di attivazione dei moduli
for (int i = 0; i < last_word; i += 4)
{
memcpy(data, &_eprom[48+i], sizeof(data));
garble(data);
if (data[3] == _serno) // Validate block
{
for (int j = 0; j < 3; j++)
{
word parola = data[j] ^ _serno;
if (parola)
{
for (int b = 15; b >= 0; b--)
{
if (test_bit(parola, b))
{
const word bit = i * 12 + j * 16 + b;
_module.set(bit+1);
}
}
}
}
}
else
break;
}
_module.set(0, true); // Forza l'attivazione della base
// Legge anno di assitenza e numero massimo di utenti
memcpy(data, &_eprom[60], sizeof(data));
garble(data);
if (already)
{
_year_assist = data[0];
_max_users = data[1];
const long giulio = *((const long*)&data[2]);
const long yyyymmdd = _last_update.julian2date(giulio);
_last_update = yyyymmdd;
}
else
{
_year_assist = 0;
_dirty = true;
}
}
else
set_developer_permissions();
}
else
_type = _no_dongle;
return ok;
}
bool TDongle::eutron_login(bool test_all_keys)
{
bool ok = false;
const char* labels[3] = { "AGA.INFORMATICA", "AGA.CAMPO", "25EBAI" };
TDongleType types[3] = { _aga_dongle, _user_dongle, _developer_dongle };
for (int k = test_all_keys ? 0 : 1; k < 3; k++)
{
const unsigned char* pwd = (const unsigned char*)::encode(labels[k]);
ok = xvt_dongle_sl_login((const unsigned char*)labels[k], pwd) != 0;
if (ok)
{
_hardware = _dongle_eutron;
_type = types[k];
break;
}
}
if (ok)
{
_serno = 0;
_max_users = 1;
_last_update = TDate(TODAY);
_year_assist = _last_update.year();
if (_type == _user_dongle) //chiave cliente
{
_module.reset(); // Disattiva tutti i moduli
if (read_words(0, sizeof(TEutronHeader) / 2, _eprom))
{
const TEutronHeader* eh = (const TEutronHeader*)_eprom;
TString16 serno; serno.strncpy(eh->_serno, 8);
_serno = unsigned(atol(serno));
if (already_programmed())
{
_max_users = eh->_max_users;
_last_update = eh->_last_date;
_year_assist = eh->_year_assist;
// Calcola il numero della word dove cominciano i bit di attivazione
unsigned short otb = eh->_offset_to_bits;
if (otb == 0) otb = 16; // Compatibile Hardlock
unsigned short sob = eh->_size_of_bits;
if (sob == 0) sob = 16; // Compatibile Hardlock
word data[64];
if (read_words(otb, sob, data))
{
int module = 1;
for (word w = 0; w < sob; w++)
{
for (int b = 0; b < 16; b++)
{
if (test_bit(data[w], b))
_module.set(module);
module++;
}
}
}
memset(_assist, 0, sizeof(_assist)); // Azzera pre-pagato
TEutronFooter ef;
if (read_words(otb+sob, sizeof(ef)/2, (word*)&ef))
{
if (ef.valid())
{
_last_assist = ef._last_assist;
memcpy(_assist, ef._assistance, sizeof(_assist));
}
}
}
else
_dirty = true;
}
_module.set(0, true); // Forza l'attivazione della base
}
else
set_developer_permissions();
}
return ok;
}
bool TDongle::network_login(bool test_all_keys)
{
const char* appname = main_app().name();
if (network() && ok())
rpc_UserLogout(appname);
TString server = "127.0.0.1";
if (!xvt_sys_dongle_server_is_running())
server = ini_get_string(CONFIG_INSTALL, "Server", "Dongle");
// const char* guest = "******";
// const TString16 appname = main_app().name();
// const char* utente = (!main_app().is_running() && appname == "ba0100") ? guest : (const char *) user();
const char* utente = user();
bool ok = rpc_UserLogin(server, utente, "******", appname);
if (ok)
{
_hardware = _dongle_network;
_type = _user_dongle;
_max_users = 1;
_last_update = TDate(TODAY);
// Let's try to spare some network band!
ok = rpc_DongleInfo(_serno, _year_assist, _module);
if (!ok)
{
_serno = rpc_DongleNumber();
_year_assist = rpc_DongleYear();
ok = rpc_DongleModules(_module);
if (ok && main_app().name() == "ba0100")
warning_box("ATTENZIONE! Il server di protezione non e' aggiornato:\n"
"Controllare la corretta installazione del servizio");
}
}
return ok;
}
int TDongle::can_try_server() const
{
// Se authoriz sta andando sono obbligato ad usarlo
if (xvt_sys_dongle_server_is_running())
return 3;
// Se sono un client ed ho l'indirizzo di authoriz sono obbligato ad usarlo
const TString& dongle = ini_get_string(CONFIG_INSTALL, "Server", "Dongle");
if (dongle.full())
return ini_get_int(CONFIG_INSTALL, "Main", "Type") == 3 ? 3 : 1;
return false;
}
bool TDongle::login(bool test_all_keys)
{
bool ok = true;
if (_type != _no_dongle) // Already logged in
logout();
TDongleHardware hw = _hardware;
if (hw == _dongle_unknown)
{
if (can_try_server())
hw = _dongle_network;
else
hw = (TDongleHardware)ini_get_int(CONFIG_INSTALL, "Main", "Donglehw");
}
switch(hw)
{
case _dongle_hardlock:
ok = hardlock_login(test_all_keys);
break;
case _dongle_eutron:
ok = eutron_login(test_all_keys);
break;
case _dongle_network:
ok = network_login(test_all_keys);
break;
default:
ok = false;
break;
}
if (!ok)
{
// retry login for various dongles ...
const int should_use_server = can_try_server();
if (should_use_server != 3) // Non sono obbligato ad usare il Dongle Server
{
if (!ok && hw != _dongle_eutron)
ok = eutron_login(test_all_keys);
if (!ok && hw != _dongle_hardlock)
ok = hardlock_login(test_all_keys);
}
if (ok)
ini_set_int(CONFIG_INSTALL, "Main", "Donglehw", (int)_hardware);
else
{ // DEMO
_hardware = _dongle_unknown;
_type = _no_dongle;
_serno = 0xFFFF; //numero di serie più alto possibile (65535 in exadecimals: non sarà mai raggiunto da chiavi clienti...magari!)
_max_users = 1;
_last_update = TDate(TODAY);
_year_assist = 3000; //anno di assistenza a 3000 per non avere problemi con le versioni nei vari anni
_module.set(ENDAUT); // Last module on key
_module.set(); // Activate all modules
_shown.reset();
}
}
return ok;
}
bool TDongle::logout()
{
switch (_hardware)
{
case _dongle_hardlock:
xvt_dongle_hl_logout();
break;
case _dongle_eutron:
xvt_dongle_sl_logout();
break;
case _dongle_network:
rpc_UserLogout(main_app().name());
break;
default:
break;
}
_type = _no_dongle;
_serno = 0xFFFF;
return true;
}
// Data punta ad un array di 4 words
// Deve essere cosi' per problemi del C,
// non trasformare in array: pena di morte!
bool TDongle::read_words(word reg, word len, word* ud) const
{
bool ok = false;
switch (_hardware)
{
case _dongle_hardlock:
{
for (word i = 0; i < len; i++)
xvt_dongle_hl_read(reg+i, &ud[i]);
ok = true;
}
break;
case _dongle_eutron:
while (len > 0)
{
const unsigned short size = (len <= 16) ? len : 16;
ok = xvt_dongle_sl_read_block(reg, size, ud) != 0;
if (!ok)
{
yesnofatal_box("EUTRON read error");
break;
}
len -= size;
reg += size;
ud += size;
}
break;
default:
break;
}
return ok;
}
// Data punta ad un array di 4 words
// Deve essere cosi' per problemi del C,
// non trasformare in array: pena di morte!
bool TDongle::write_words(word reg, word len, word* data) const
{
bool ok = false;
switch(_hardware)
{
case _dongle_hardlock:
{
for (word r = 0; r < len; r++)
{
const word address = reg+r;
ok = xvt_dongle_hl_write(address, data[r]) != 0;
}
}
break;
case _dongle_eutron:
while (len > 0)
{
const unsigned short size = (len <= 16) ? len : 16;
ok = xvt_dongle_sl_write_block(reg, size, data) != 0;
if (!ok)
break;
len -= size;
reg += size;
data += size;
}
break;
default:
break;
}
return ok;
}
int TDongle::oem() const
{
if (_OEM < 0)
{
TString& firm = (TString&) _reseller;
TString& campo = (TString&) _product;
TString& breve = (TString&) _shortname;
TString& admin = (TString&)_admin;
TString& admpwd = (TString&)_admpwd;
int& oem = (int&)_OEM;
//nuovo metodo di rilevamento producer (dalla 10.0 in avanti); il producer sta nel file oem.ini sotto la cartella
//setup, sia nel CD che soprattutto nel programma installato
TConfig ini(CONFIG_OEM, "MAIN");
oem = ini.get_int("OEM", NULL, -1, -1);
if (oem >= 0)
{
TString8 para; para << "OEM_" << oem;
ini.set_paragraph(para);
campo = decode(ini.get("Product"));
firm = decode(ini.get("Reseller"));
breve = decode(ini.get("Name"));
admin = decode(ini.get("Administrator"));
admpwd = decode(ini.get("Password"));
}
if (firm.blank()) //vecchio metodo di rilevamento del producer: sta in install.ini
{
firm = decode(ini_get_string(CONFIG_GENERAL, "Main", "Producer"));
campo = breve = " ";
}
//nuovo metodo: cerca produttore (Name) e prodotto (Product)
if (firm.blank())
{
ignore_xvt_errors(true);
char* p = firm.get_buffer(80);
xvt_res_get_str(STR_FIRMNAME, p, firm.size());
ignore_xvt_errors(false);
}
if (admin.blank())
{
admin = decode(ini_get_string(CONFIG_GENERAL, "Main", "Administrator"));
if (admin.blank())
{
admin = "ADMIN";
admpwd = "ad.min";
}
}
if (admpwd.blank())
{
admpwd = decode(ini_get_string(CONFIG_GENERAL, "Main", "Password"));
if (admpwd.blank())
{
admpwd = admin;
admpwd.lower();
admpwd.insert(".", 2);
}
}
if (campo.blank())
campo = "Campo Enterprise";
if (firm.blank())
firm = "AGA informatica s.r.l.";
if (breve.blank())
breve = "Campo";
if (oem < 0)
oem = firm.starts_with("AGA ") ? 0 : 1;
}
return _OEM;
}
// Ritorna il nome della ditta che vende il programma attuale
const TString& TDongle::reseller() const
{
if (_reseller.empty())
oem();
return _reseller;
}
const TString& TDongle::product() const
{
if (_product.empty())
oem();
return _product;
}
const TString& TDongle::short_name() const
{
if (_shortname.empty())
oem();
return _shortname;
}
const TString& TDongle::server_name() const
{
if (network() && !xvt_sys_dongle_server_is_running())
return ini_get_string(CONFIG_INSTALL, "Server", "Dongle");
TString& tmp = get_tmp_string(32);
xvt_sys_get_host_name(tmp.get_buffer(), tmp.size());
return tmp;
}
bool TDongle::active(word module) const
{
const bool yes = (module < ENDAUT) && _module[module] && shown(module);
return yes;
}
bool TDongle::activate(word module, bool on)
{
bool ok = module < ENDAUT;
if (ok)
{
_module.set(module, on && shown(module));
_dirty = true;
}
return ok;
}
bool TDongle::burn_hardlock()
{
word data[4];
const TDate today(TODAY);
const bool already = already_programmed();
if (already)
{
memcpy(data, &_eprom[60], sizeof(data));
garble(data);
if (data[0] < 2001 || data[0] > 3001)
return error_box("On Line Assistance error.");
if (data[1] == 0 || data[1] >= 10000)
return error_box("Bad users number.");
const long val = *((const long*)&data[2]);
const long yyyymmdd = today.julian2date(val);
const TDate date(yyyymmdd);
if (date > today)
return error_box("Too late sir: key has already expired!");
}
data[0] = _year_assist;
data[1] = _max_users;
long* val = (long*)&data[2];
*val = today.date2julian();
garble(data);
write_words(60, 4, data);
_last_update = today;
// Il primo bit della memoria della chiave corrisponde al modulo uno
// non allo zero (che e' la base ed e' sempre attivo)
word module = 1;
for (int octect = 0; octect < 3; octect++)
{
for(int parola = 0; parola < 3; parola++)
{
word& p = data[parola];
p = 0;
for (int bit = 0; bit < 16; bit++)
{
if (active(module))
set_bit(p, bit);
module++;
}
p ^= _serno;
}
data[3] = _serno;
garble(data);
write_words(48 + 4*octect, 4, data);
}
return true;
}
bool TDongle::burn_eutron()
{
TEutronHeader* eh = (TEutronHeader*)_eprom;
memset(eh, 0, sizeof(TEutronHeader));
_last_update = TDate(TODAY);
sprintf(eh->_serno, "%lu", (unsigned long)_serno);
eh->_year_assist = _year_assist;
eh->_max_users = _max_users;
eh->_last_date = atol(_last_update.string(ANSI));
eh->_scad_date = 0;
unsigned long cs = 0;
for (byte* ptr = (byte*)_eprom; ptr < (byte*)&eh->_checksum; ptr++)
cs += *ptr | ~(short(*ptr << 8));
eh->_checksum = cs;
const word otb = sizeof(TEutronHeader) / 2;
const word sob = 16;
eh->_offset_to_bits = otb;
eh->_size_of_bits = sob;
bool ok = write_words(0, otb, _eprom);
if (ok)
{
word data[sob]; memset(data, 0, sizeof(data));
for (int module = 1; module < 256; module++)
{
if (active(module))
{
word& w = data[(module-1) / 16];
set_bit(w, (module-1) % 16, true);
}
}
ok = write_words(otb, sob, data);
}
if (ok)
{
TEutronFooter ef;
CHECK(sizeof(ef._assistance) == sizeof(_assist), "Assistance size mismatch");
ef._last_assist = _last_assist.year()*10000L + _last_assist.month()*100L + _last_assist.day();
memcpy(ef._assistance, _assist, sizeof(_assist));
ef.checksum(true);
ok = write_words(otb+sob, word(ef._size/2), (word*)&ef);
}
return ok;
}
bool TDongle::burn()
{
bool ok = local() && _type == _user_dongle;
if (ok)
{
switch(_hardware)
{
case _dongle_hardlock: ok = burn_hardlock(); break;
case _dongle_eutron : ok = burn_eutron(); break;
default : break;
}
}
if (ok)
_dirty = false;
return ok;
}
/*
#define BIT31 (1L<<31)
#define MSK31 (~BIT31)
real TDongle::residual_assist(int index, bool lire) const
{
real imp;
if (index >= 0 && index < MAX_DONGLE_ASSIST)
{
imp = (_assist[index] & MSK31) / 100.0;
if (lire)
{ imp *= 1936.27; imp.round(-2); }
}
return imp;
}
bool TDongle::can_require_assist(int index) const
{
bool ok = false;
if (index >= 0 && index < MAX_DONGLE_ASSIST)
{
const TDate oggi(TODAY);
if (oggi == _last_assist)
ok = (_assist[index] & BIT31) == 0;
else
ok = oggi > _last_assist;
}
return ok;
}
bool TDongle::require_assist(int index, real imp, bool lire)
{
imp *= 100;
if (lire) { imp /= 1936.27; imp.round(2); }
bool ok = false;
if (imp > ZERO)
{
if (can_require_assist(index))
{
const TDate oggi(TODAY);
if (oggi > _last_assist)
{
for (int i = 0; i < MAX_DONGLE_ASSIST; i++)
_assist[index] &= MSK31;
_last_assist = oggi;
}
_assist[index] &= MSK31;
_assist[index] += imp.integer();
_assist[index] |= BIT31;
_dirty = true;
ok = burn();
}
}
return ok;
}
bool TDongle::pay_assist(int index, real imp, bool lire)
{
bool ok = imp > ZERO;
if (ok)
{
imp *= 100;
if (lire) { imp /= 1936.27; imp.round(2); }
unsigned long old_bit31 = _assist[index] & BIT31;
_assist[index] &= MSK31;
_assist[index] -= imp.integer();
_assist[index] |= old_bit31;
_dirty = true;
ok = burn();
}
return ok;
}
*/
const TString_array& TDongle::info() const
{
if (_info.items() == 0)
{
TScanner scanner("campo.aut");
for (int aut = 0; ; aut++)
{
const TString& row = scanner.line();
if (row.blank())
break;
TToken_string* tok = new TToken_string;
tok->strncpy(row, 3);
const TString& name = row.mid(3);
if (name.full())
*tok << dictionary_translate(name);
((TString_array&)_info).add(tok);
}
}
return _info;
}
word TDongle::module_name2code(const char* mod) const
{
int i = BAAUT;
if (mod && *mod && xvt_str_compare_ignoring_case(mod, "sy") != 0)
{
if (real::is_natural(mod))
{
i = atoi(mod);
// Trasforma i numeri da 74 a 77 nei codici da M74AUT a M77AUT
if (i >= 74 && i <= 77)
i += M74AUT-74;
}
else
{
const TString_array& modinfo = info();
for (i = modinfo.last(); i >= 0; i--)
{
const TString& autstr = modinfo.row(i);
if (autstr.starts_with(mod, true))
break;
}
}
}
return word(i);
}
const TString& TDongle::module_code2name(word mod) const
{
const TString_array& modinfo = info();
if (mod < modinfo.items())
return modinfo.row(mod).left(2);
return EMPTY_STRING;
}
const TString& TDongle::module_code2desc(word mod) const
{
const TString_array& modinfo = info();
return mod < modinfo.items() ? modinfo.row(mod).mid(3) : EMPTY_STRING;
}
const TString& TDongle::module_name2desc(const char* mod) const
{
const word cod = module_name2code(mod);
if (cod == 0)
{
if (xvt_str_compare_ignoring_case(mod, "sy") == 0)
return get_tmp_string() = TR("Sistema");
}
return module_code2desc(cod);
}
bool TDongle::shown(word code) const
{
bool yes = code < ENDAUT;
if (yes)
{
yes = _shown[code];
if (!yes) // Puo' voler dire "nascosto" ma anche "non ho mai controllato"
{
const TString4 mod = module_code2name(code);
yes = mod.not_empty();
if (yes && code > BAAUT && code < ENDAUT)
{
TAuto_token_string ee = ini_get_string(CONFIG_GENERAL, mod, "OEM"); // Modern OEM handling
if (ee.full())
yes = ee.get_pos(oem()) >= 0;
}
if (yes)
((TBit_array&)_shown).set(code); // Setto il flag di visibilta' per la prossima volta
}
}
return yes;
}
bool TDongle::demo() const
{ return hardware() == _dongle_unknown && type() == _no_dongle; }
///////////////////////////////////////////////////////////////////////////////
// TEnigma_machine
///////////////////////////////////////////////////////////////////////////////
#define DNINST_PATH "setup/dninst.zip"
class TEnigma_machine : public TObject
{
TScanner* _scan;
int _year_assist;
protected:
void init_key(char key[8]) const;
bool decode_string(const TString& datain, TString& dataout) const;
public:
virtual bool ok() const { return _scan != NULL && !_scan->eof(); }
bool line(TString& data);
bool find_serno(long serno);
int year_assist() const { return _year_assist; }
TEnigma_machine();
~TEnigma_machine();
};
void TEnigma_machine::init_key(char key[8]) const
{
for (int i = 0; i < 8; i++)
key[i] = 'A' + ::rand() % 26;
}
bool TEnigma_machine::decode_string(const TString& datain, TString& dataout) const
{
dataout.cut(0);
if (datain.not_empty())
{
char* tmp = dataout.get_buffer(datain.len());
char key[8]; init_key(key);
int i;
for (i = 0; datain[i]; i++)
tmp[i] = datain[i] - (i < 8 ? key[i] : tmp[i - 8]);
tmp[i] = '\0';
}
return dataout.full();
}
bool TEnigma_machine::line(TString& data)
{ return _scan != NULL ? decode_string(_scan->line(), data) : false; }
bool TEnigma_machine::find_serno(long serno)
{
if (serno == 0)
return true;
TToken_string row(80, ';');
if (_year_assist > 2100)
{
TString8 para; para << '[' << serno << ']';
while (line(row))
{
if (row == para)
return true;
}
}
else
{
while (line(row))
{
if (row.get_long(0) == serno)
return true;
}
}
return false;
}
TEnigma_machine::TEnigma_machine()
: _scan(NULL), _year_assist(0)
{
if (fexist(DNINST_PATH))
{
_scan = new TScanner(DNINST_PATH);
::srand(883);
TString4 l1; line(l1);
_year_assist = atoi(l1);
::srand(_year_assist);
}
}
TEnigma_machine::~TEnigma_machine()
{
if (_scan != NULL)
delete _scan;
}
int Tdninst::assistance_year2solar(int ay) const
{ return (ay/1000)*1000 + (ay%1000)/10; }
int Tdninst::parse_date(const TString& line, TString& key, TDate& datascad) const
{
const int equal = line.find('=');
if (equal > 0 && equal <= 16)
{
key = line.left(equal); key.trim();
TString16 strdate = line.mid(equal+1, 16); strdate.trim();
if (strdate.empty())
{
datascad = TODAY; // Mettiamo una data valida comunque
return key.full() ? 1 : 0;
}
int d, m, y;
if (sscanf(strdate, "%2d-%2d-%4d", &d, &m, &y) == 3)
{
datascad = TDate(d, m, y);
return datascad.ok() ? 2 : 0;
}
}
return 0;
}
int Tdninst::test_cmdline(const TString& cmdline, bool key_must_exist, TString& msg) const
{
msg.cut(0);
const TDongle& don = dongle();
const long serno = don.number();
if (serno == 0)
{
if (is_power_reseller(true))
return 0; // Solo chiavi per uso interno aga
msg = TR("Chiave di sviluppo non autorizzata");
return 1;
}
const TString4 strmod = cmdline.left(2);
if (!key_must_exist) // Le personalizzazioni non hanno un modulo vero e proprio
{
const int space_pos = cmdline.find(' ');
if (space_pos < 0 || space_pos == 3)
{
const word codmod = don.module_name2code(strmod);
if (codmod == BAAUT)
return 0;
/*if (!don.active(codmod))
{
msg << TR("Modulo non attivo sulla chiave: ") << strmod;
return 2;
}*/
}
}
const TDate oggi(TODAY);
const int solar_year = oggi.year();
const int dongle_ass = don.year_assist();
const int dongle_year = assistance_year2solar(dongle_ass);
if (solar_year - dongle_year >= 2)
{
msg << TR("Anno di assitenza non valido sulla chiave: ") << dongle_year;
return 3;
}
TEnigma_machine em;
const int dninst_ass = em.year_assist();
if (dongle_ass > dninst_ass)
{
msg << TR("File dninst.zip obsoleto");
return 4;
}
bool bFound = false;
if (dninst_ass > 2100)
{
if (em.find_serno(serno))
{
TString80 dninst_line;
TString16 key;
TDate datascad;
while (em.line(dninst_line))
{
if (dninst_line.empty() || dninst_line.starts_with("["))
break; // Fine file o paragrafo
if (parse_date(dninst_line, key, datascad))
{
const bool scaduto = datascad < oggi;
if (key == "*")
{
if (scaduto)
{
msg << TR("Chiave scaduta il ") << datascad;
return 7;
}
} else
if (key == cmdline)
{
bFound = true;
if (scaduto)
{
msg << TR("Applicazione scaduta il ") << datascad;
return 8;
}
} else
if (key == strmod)
{
if (scaduto)
{
msg << TR("Modulo scaduto il ") << datascad;
return 9;
}
}
}
}
}
}
else
{
TToken_string dninst_line(80, ';');
while (em.line(dninst_line))
{
bFound = dninst_line.get_long(0) == serno;
if (bFound)
{
if (dninst_line.get_pos(strmod) > 0)
{
msg << TR("Modulo non attivo in dninst.zip : ") << strmod;
return 5;
}
break;
}
}
}
if (!bFound && key_must_exist)
{
msg << TR("Impossibile trovare ") << cmdline;
return 6;
}
return 0;
}
bool Tdninst::can_I_run(const bool is_personal_program) const
{
TFilename cmdline = main_app().argv(0);
cmdline = cmdline.name_only();
if (cmdline.starts_with("ba", true) || cmdline.ends_with("cnv", true))
return true;
const bool me = is_personal_program || cmdline.len()>3;
const char* option = main_app().argc() > 1 ? main_app().argv(1) : "";
if (*option == '-' && isdigit(*(option+1)))
cmdline << ' ' << option;
cmdline.lower();
TString msg;
return test_cmdline(cmdline, me, msg) == 0;
}
bool Tdninst::find_killed(TToken_string& kill_list) const
{
kill_list.cut(0);
const int serno = dongle().number();
if (serno == 0)
return true;
bool good = false;
TEnigma_machine em;
if (em.ok())
{
if (em.year_assist() > 2100)
{
TToken_string l(80, '=');
good = em.find_serno(serno);
if (good)
{
const TDate oggi(TODAY);
TString16 str;
TDate ds;
while (em.line(l))
{
if (l.empty() || l[0] == '[')
break;
if (parse_date(l, str, ds) && ds < oggi)
kill_list.add(str);
}
}
}
else
{
TToken_string l(80, ';');
while (em.line(l))
{
if (l.get_long(0) == serno)
{
const int semicolon = l.find(l.separator());
if (semicolon > 0)
{
kill_list = l.mid(semicolon+1);
kill_list.lower();
kill_list.replace(l.separator(), kill_list.separator());
}
good = true;
break;
}
}
}
}
return good;
}
Tdninst::Tdninst() : _year_assist(0)
{
TEnigma_machine s;
_year_assist = s.year_assist(); // 2091 or 2101?
}