campo-sirio/include/dongle.cpp
luca 8bfb893da5 Patch level :
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :


git-svn-id: svn://10.65.10.50/trunk@18785 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-04-27 15:18:07 +00:00

1100 lines
25 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
///////////////////////////////////////////////////////////
#ifndef _DEMO_
#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);
}
#endif // _DEMO_
///////////////////////////////////////////////////////////
// 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(2006), _dirty(false)
{
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())
{
TString& admin = (TString&)_admin; // Sorry
TString& admpwd = (TString&)_admpwd; // Sorry
//nuovo metodo di rilevamento administrator (dalla 10.0 in avanti); l'admin sta nel file oem.ini sotto la cartella
//setup, sia nel CD che soprattutto nel programma installato
int oem = -1;
if (oem < 0)
{
TConfig ini(CONFIG_OEM, "MAIN");
oem = ini.get_int("OEM", NULL, -1, -1);
if (oem >= 0)
{
TString8 para; para << "OEM_" << oem;
admin = ini.get("Administrator", para);
admpwd = ini.get("Password", para);
}
}
//vecchio metodo di rilevamento dell'admin e della sua password: sta in install.ini
//administrator
if (oem < 0)
{
TConfig ini("install.ini", "Main");
admin = ini.get("Administrator");
admpwd = ini.get("Password");
}
if (admin.blank())
admin = "ADMIN";
else
admin = ::decode(_admin);
//password
if (admpwd.blank())
{
admpwd = admin;
admpwd.lower();
admpwd.insert(".", 2);
}
else
admpwd = ::decode(admpwd);
}
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
{
#ifndef _DEMO_
switch (_hardware)
{
case _dongle_hardlock:
xvt_dongle_hl_crypt(data);
break;
case _dongle_eutron:
xvt_dongle_sl_crypt(data);
break;
default:
break;
}
#endif
}
bool TDongle::already_programmed() const
{
#ifndef _DEMO_
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!
}
#endif // _DEMO_
return true;
}
#ifndef _DEMO_
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);
TConfig ini(CONFIG_INSTALL, "Server");
const char* server = ini.get("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();
const bool ok = rpc_UserLogin(server, utente, "******", appname);
if (ok)
{
_hardware = _dongle_network;
_type = _user_dongle;
_serno = rpc_DongleNumber();
_max_users = 1;
_last_update = TDate(TODAY);
_year_assist = rpc_DongleYear();
rpc_DongleModules(_module);
}
return ok;
}
#endif // _DEMO_
int TDongle::can_try_server() const
{
if (xvt_sys_dongle_server_is_running())
return 3;
TConfig ini(CONFIG_INSTALL, "Server");
const TString& dongle = ini.get("Dongle");
return dongle.full();
}
bool TDongle::login(bool test_all_keys)
{
bool ok = true;
#ifdef _DEMO_
_hardware = _dongle_unknown;
_type = _user_dongle;
_serno = 0;
_max_users = 1;
_last_update = TDate(TODAY);
_year_assist = _last_update.year();
_module.set(ENDAUT); // Last module on key
_module.set(); // Activate all modules
_shown.reset();
#else
if (_type != _no_dongle) // Already logged in
logout();
TDongleHardware hw = _hardware;
if (hw == _dongle_unknown)
{
if (can_try_server())
{
hw = _dongle_network;
}
else
{
TConfig ini(CONFIG_INSTALL, "Main");
hw = (TDongleHardware)ini.get_int("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 use_server = can_try_server();
if (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)
{
TConfig ini(CONFIG_INSTALL, "Main");
ini.set("Donglehw",(int)_hardware);
}
}
#endif
return ok;
}
bool TDongle::logout()
{
#ifndef _DEMO_
if (_type != _no_dongle)
{
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;
}
}
#endif
_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;
#ifndef _DEMO_
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;
}
#endif // _DEMO_
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;
#ifndef _DEMO_
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;
}
#endif // _DEMO_
return ok;
}
// Ritorna il nome della ditta che vende il programma attuale
const TString& TDongle::reseller() const
{
if (_reseller.blank())
{
TString& firm = (TString&) _reseller;
TString& campo = (TString&) _product;
TString& breve = (TString&) _shortname;
//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
int oem = -1;
if (oem < 0)
{
TConfig ini(CONFIG_OEM, "MAIN");
oem = ini.get_int("OEM", NULL, -1, -1);
if (oem >= 0)
{
TString8 para; para << "OEM_" << oem;
campo = ini.get("Product", para);
firm = ini.get("Reseller", para);
breve = ini.get("Name", para);
}
}
if (firm.blank()) //vecchio metodo di rilevamento del producer: sta in install.ini
{
TConfig ini("install.ini", "Main");
firm = ini.get("Producer");
campo = breve = " ";
}
//nuovo metodo: cerca produttore (Name) e prodotto (Product)
if (firm.full())
{
firm = decode(firm);
campo = decode(campo);
breve = decode(breve);
}
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 (campo.blank())
campo = "Campo Enterprise";
if (firm.blank())
firm = "AGA informatica s.r.l.";
if (breve.blank())
breve = "Campo";
}
return _reseller;
}
const TString& TDongle::product() const
{
if (_product.empty())
reseller();
return _product;
}
const TString& TDongle::shortname() const
{
if (_shortname.empty())
reseller();
return _shortname;
}
bool TDongle::active(word module) const
{
bool yes = false;
if (module == EEAUT)
{
const TString& r = reseller();
yes = r.starts_with("AGA ");
}
else
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;
}
#ifndef _DEMO_
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] < 1997 || data[0] > 2997)
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;
}
#endif // _DEMO_
bool TDongle::burn()
{
bool ok = local() && _type == _user_dongle;
#ifndef _DEMO_
if (ok)
{
switch(_hardware)
{
case _dongle_hardlock: ok = burn_hardlock(); break;
case _dongle_eutron : ok = burn_eutron(); break;
default : break;
}
}
#endif
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 = 0;
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--)
{
if (modinfo.row(i).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);
else
{
if (mod == EEAUT)
return get_tmp_string() = "ee";
}
return EMPTY_STRING;
}
const TString& TDongle::module_code2desc(word mod) const
{
const TString_array& modinfo = info();
if (mod < modinfo.items())
return modinfo.row(mod).mid(3);
else
{
if (mod == EEAUT)
return get_tmp_string() = "Enterprise Edition";
}
return 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)
{
bool do_test = true;
if (code != EEAUT)
{
TConfig cfg("install.ini", mod);
cfg.write_protect();
do_test = cfg.get_bool("Ee");
}
if (do_test)
yes = active(EEAUT);
}
if (yes)
((TBit_array&)_shown).set(code); // Setto il flag di visibilta' per la prossima volta
}
}
return yes;
}