campo-sirio/ba/ba1400.cpp

867 lines
20 KiB
C++
Raw Normal View History

#include <colors.h>
#include <modaut.h>
#include <msksheet.h>
#include <relapp.h>
#include <utility.h>
#include <tree.h>
#include <treectrl.h>
#include <urldefid.h>
#include "ba1.h"
#include "ba1500.h"
#include "ba1400a.h"
#include <user.h>
///////////////////////////////////////////////////////////
// Menu item
///////////////////////////////////////////////////////////
class TMenu_item : public TString
{
TString _cmd;
public:
virtual TObject* dup() const { return new TMenu_item(*this); }
const TString& cmd() const { return _cmd; }
TString& cmd() { return _cmd; }
TMenu_item(const TMenu_item& mi);
TMenu_item(const char* line);
virtual ~TMenu_item() { }
};
TMenu_item::TMenu_item(const TMenu_item& mi)
: _cmd(mi._cmd)
{ set(*this); }
TMenu_item::TMenu_item(const char* line)
{
TToken_string ts(line, ',');
set(ts.get(0)); trim();
if (operator[](0) == '"')
{ ltrim(1); rtrim(1); }
_cmd = ts.get(); _cmd.trim();
if (_cmd[0] == '"')
{ _cmd.ltrim(1); _cmd.rtrim(1); }
}
///////////////////////////////////////////////////////////
// Sottomenu (lista di menu items)
///////////////////////////////////////////////////////////
class TSubmenu : public TString
{
TArray _child;
word _module;
public:
TMenu_item& operator[](int c) { return (TMenu_item&)*_child.objptr(c); }
TMenu_item& add_child(const char* line);
int items() const { return _child.items(); }
int module() const { return _module; }
void set_module(word m) { _module = m; }
TSubmenu& operator=(const char* str) { set(str); return *this; }
TSubmenu& operator=(const TSubmenu& str) { set(str); _module = str._module; return *this; }
TSubmenu() : _module(0) { }
virtual ~TSubmenu() { }
};
TMenu_item& TSubmenu::add_child(const char* line)
{
TMenu_item* item = new TMenu_item(line);
_child.add(item, -1);
return *item;
}
///////////////////////////////////////////////////////////
// Nodo dell'albero del menu principale
///////////////////////////////////////////////////////////
class TMenu_node : public TString
{
TMenu_item* _item;
int _module;
public:
const TString& command() const;
int module() const { return _module; }
TMenu_node(TMenu_item* i, int module = 0);
TMenu_node(const char* str);
};
const TString& TMenu_node::command() const
{
if (_item)
return _item->cmd();
return EMPTY_STRING;
}
TMenu_node::TMenu_node(TMenu_item* i, int module)
: _item(i), _module(module)
{
set(*i);
}
TMenu_node::TMenu_node(const char* str)
: _item(NULL), _module(0)
{
set(str);
}
///////////////////////////////////////////////////////////
// Menu tree (albero di menu nodes)
///////////////////////////////////////////////////////////
class TMenu : public TObject_tree
{
TAssoc_array _submenu; // Insieme dei sottomenu
TAssoc_array _prop; // Proprieta' dei singoli programmi
protected:
virtual bool add_son(TObject* son);
virtual bool get_description(TString& desc) const;
virtual TImage* image(bool selected) const;
protected:
TSubmenu& get_submenu(const char* name);
TSubmenu& add_submenu(const char* para, int parent_module);
void import(const char* filename, TString& first);
public:
virtual bool enabled() const;
TAssoc_array& properties() { return _prop; }
TString_array& properties(const char* cmd);
const TString_array* find_properties(const char* cmd) const;
TMenu(const char* name);
virtual ~TMenu() { }
};
///////////////////////////////////////////////////////////
// Main app
///////////////////////////////////////////////////////////
class TSet_user_passwd : public TRelation_application
{
protected:
TMask* _msk;
TRelation* _rel;
TInformazione_moduli* _im;
protected:
virtual bool user_create();
virtual bool user_destroy();
virtual TMask* get_mask(int mode) { return _msk; }
virtual bool changing_mask(int mode) { return false; }
virtual TRelation* get_relation() const { return _rel; }
virtual int read(TMask& m);
virtual void init_query_mode(TMask& m);
virtual void init_modify_mode(TMask& m);
virtual void init_insert_mode(TMask& m) { build_sheet(NULL); }
protected:
void save_password(const TMask& m, TRectype& r) const;
virtual void put_in_record(const TMask& m);
virtual int write(const TMask& m);
virtual int rewrite(const TMask& m);
TSheet_field& sheet_field() { return _msk->sfield(F_MODULI); }
void build_sheet(const TRectype* r);
void enable_aut();
static bool password_handler(TMask_field& f, KEY key);
public:
bool user_has_module(int mod);
TSet_user_passwd() : _msk(NULL), _rel(NULL) , _im(NULL) {}
};
class TSet_users : public TSet_user_passwd
{
TMenu* _tree;
protected:
virtual bool user_create();
virtual bool user_destroy();
virtual TMask* get_mask(int mode) { return _msk;}
virtual bool changing_mask(int mode) { return false;}
virtual TRelation* get_relation() const { return _rel;}
virtual int read(TMask& m);
virtual bool remove();
virtual void init_query_mode(TMask& m) { enable_aut(); }
virtual void init_insert_mode(TMask& m) { build_sheet(NULL); }
virtual void init_modify_mode(TMask& m) { enable_aut();}
protected:
void build_tree(const TRectype* r);
virtual void put_in_record(const TMask& m);
static bool user_handler(TMask_field& f, KEY key);
static bool group_handler(TMask_field& f, KEY key);
static bool k_notify(TSheet_field & f, int r, KEY k);
static bool tree_handler(TMask_field& f, KEY key);
static bool p_notify(TSheet_field & f, int r, KEY k);
public:
TSet_users() : TSet_user_passwd() , _tree(NULL) {}
};
inline TSet_users& app() { return (TSet_users&)main_app(); }
///////////////////////////////////////////////////////////
// Menu tree implementation
///////////////////////////////////////////////////////////
const TString_array* TMenu::find_properties(const char* cmd) const
{
const TString_array* arr = (const TString_array*)_prop.objptr(cmd);
return arr;
}
TString_array& TMenu::properties(const char* cmd)
{
TString_array* arr = (TString_array*)_prop.objptr(cmd);
if (arr == NULL)
{
arr = new TString_array;
_prop.add(cmd, arr);
}
return *arr;
}
bool TMenu::add_son(TObject* son)
{
if (goto_firstson())
{
while (goto_rbrother());
return add_rbrother(son);
}
return TObject_tree::add_son(son);
}
bool TMenu::get_description(TString& desc) const
{
TMenu_node* node = (TMenu_node*)curr_node();
if (node) desc = *node;
return node != NULL;
}
bool TMenu::enabled() const
{
TMenu_node* node = (TMenu_node*)curr_node();
const int mod = node->module();
return app().user_has_module(mod);
}
TImage* TMenu::image(bool selected) const
{
TMenu_node* node = (TMenu_node*)curr_node();
if (!has_son())
{
const TString& cmd = node->command();
if (cmd.not_empty())
{
const TString_array* prop = find_properties(cmd);
if (prop)
{
TString80 action;
FOR_EACH_ARRAY_ROW_BACK(*prop, r, row)
{
row->get(1, action);
if (action == "Negato")
return get_res_icon(10203);
}
}
}
}
return TObject_tree::image(selected);
}
TSubmenu& TMenu::get_submenu(const char* name)
{
TSubmenu* sub = (TSubmenu*)_submenu.objptr(name);
if (sub == NULL)
{
sub = new TSubmenu;
_submenu.add(name, sub);
}
return *sub;
}
void TMenu::import(const char* filename, TString& first)
{
TFilename fname(filename); fname.custom_path();
TScanner scan(fname);
first.cut(0);
TSubmenu* sub = NULL;
while (scan.good())
{
TString& line = scan.line();
if (line[0] == '[')
{
if (first.empty())
first = line;
sub = &get_submenu(line);
}
else
{
if (sub != NULL)
{
if (line.starts_with("Caption", true))
{
CHECK(sub, "Invalid menu file");
const int equal = line.find('=');
CHECK(equal > 0, "Invalid menu Caption");
line.ltrim(equal+1);
line.strip("\"");
*sub = line;
} else
if (line.starts_with("Module", true))
{
CHECK(sub, "Invalid menu file");
const int equal = line.find('=');
CHECK(equal > 0, "Invalid menu Module");
const word mod = atoi(line.mid(equal+1));
sub->set_module(mod);
} else
if (line.starts_with("Item", true))
{
CHECK(sub, "Invalid menu file");
const int equal = line.find('=');
CHECK(equal > 0, "Invalid menu Item");
line.ltrim(equal+1);
line.trim();
const int bracket = line.rfind('<');
if (bracket > 0)
{
const int endbracket = line.find('>', bracket);
TFilename name = line.sub(bracket+1, endbracket);
if (name.custom_path())
{
const TString& mod = name.name_only().left(2);
const word cod = dongle().module_name2code(mod);
const bool proceed = dongle().shown(cod);
if (proceed)
{
import(name, name);
TMenu_item& child = sub->add_child(line);
child.cmd() = name;
}
}
}
else
sub->add_child(line);
}
}
}
}
}
TSubmenu& TMenu::add_submenu(const char* para, int parent_module)
{
TSubmenu& sub = get_submenu(para);
int module = sub.module();
if (module == 0)
module = parent_module;
TString id; curr_id(id);
for (int i = 0; i < sub.items(); i++)
{
goto_node(id);
add_son(new TMenu_node(&sub[i], module));
if (sub[i].cmd()[0] == '[')
add_submenu(sub[i].cmd(), module);
}
return sub;
}
TMenu::TMenu(const char* menuname)
{
TString root;
import(menuname, root);
add_son(new TMenu_node(TR("Menu Principale")));
add_submenu(root, 0);
goto_root();
expand();
}
///////////////////////////////////////////////////////////
// Main application
///////////////////////////////////////////////////////////
bool TSet_users::user_handler(TMask_field& f, KEY key)
{
if (!f.mask().query_mode() || !f.to_check(key))
return true;
const bool ok = f.get().find(' ') < 0;
if (!ok)
return f.error_box(TR("Il nome dell'utente non deve contenere spazi"));
return ok;
}
bool TSet_users::group_handler(TMask_field& f, KEY key)
{
if (key == K_TAB && f.focusdirty())
{
TMask& m = f.mask();
const TString& gruppo = m.get(F_GROUPNAME);
TEdit_field& ef = (TEdit_field&)f;
TRectype& rec = ef.browse()->cursor()->curr();
if (rec.get(USR_USERNAME) != gruppo)
{
rec.put(USR_USERNAME, gruppo);
ef.browse()->cursor()->read();
}
app().build_sheet(&rec);
}
return true;
}
bool TSet_user_passwd::password_handler(TMask_field& f, KEY key)
{
bool ok = true;
if (key == K_ENTER && f.active() && !f.mask().query_mode())
{
const TString& pwd = f.get();
const int pwdlen = pwd.len();
for (int i = pwdlen-1; i >= 0; i--)
{
if (pwd[i] >= 0 && pwd[i] <= ' ')
{
ok = error_box(FR("La password contiene un carattere non valido alla posizione %d"), i+1);
break;
}
}
if (ok)
{
const int minlen = ini_get_int(CONFIG_STUDIO, "Main", "MinPwdLen", 4);
if (pwdlen < minlen)
{
TString msg; msg.format(TR("La password deve essere lunga almeno %d caratteri."), minlen);
if (pwdlen == 0 && user() == dongle().administrator())
{
msg << '\n' << TR("Si desidera continuare ugualmente?");
ok = yesno_box(msg);
}
else
ok = f.error_box(msg);
}
}
}
return ok;
}
bool TSet_users::tree_handler(TMask_field& f, KEY key)
{
TTree_field& tf = (TTree_field&)f;
TMenu* menu = (TMenu*)tf.tree();
const TMenu_node* node = (const TMenu_node*)(menu ? menu->curr_node() : NULL);
if (node)
{
if (key == K_SPACE || key == K_ENTER)
{
TMask& m = f.mask();
TSheet_field& sf = m.sfield(F_PROPERTIES);
const TString& old = m.get(F_APPLICAT);
if (old.full())
{
menu->properties(old) = sf.rows_array();
const TString4 mod = old.left(2);
TString_array& mprop = menu->properties(mod);
if (m.get_bool(F_NOWRITE))
{
if (mprop.items() == 0)
{
TToken_string* ts = new TToken_string("S|Scrittura|0", sf.separator());
ts->replace('|', sf.separator());
mprop.add(ts);
}
}
else
mprop.destroy();
sf.destroy();
m.reset(F_APPLICAT);
m.reset(F_NOWRITE); m.disable(F_NOWRITE);
}
if (menu->enabled())
{
const TString& cmd = node->command();
if (cmd[0] != '[')
{
m.set(F_APPLICAT, cmd);
const TString_array* prop = menu->find_properties(cmd);
if (prop)
{
sf.rows_array() = *prop;
FOR_EACH_SHEET_ROW(sf, r, n)
sf.check_row(r);
sf.force_update();
}
const TString4 mod = cmd.left(2);
const TString_array* mprop = menu->find_properties(mod);
m.enable(F_NOWRITE);
m.set(F_NOWRITE, mprop && mprop->items() ? "X" : "");
m.field(F_NOWRITE).set_dirty(false);
}
}
}
}
return true;
}
bool TSet_users::p_notify(TSheet_field& f, int r, KEY k)
{
switch(k)
{
case K_INS:
{
TMask& m = f.mask();
if (m.get(F_APPLICAT).empty())
return error_box(TR("Nessun programma selezionato"));
}
default:
break;
}
return true;
}
void TSet_user_passwd::build_sheet(const TRectype* r)
{
TString autstr, d;
if (r != NULL)
autstr = r->get(USR_AUTSTR);
const int l = autstr.len();
TSheet_field& sf = sheet_field();
sf.destroy();
for (int i = 0; i < ENDAUT; i++)
{
d = _im->get_description_by_order(i);
if (d.trim().empty())
continue;
TToken_string& riga = sf.row(i);
riga = d;
const int module = _im->get_module_by_order(i);
if (r!= NULL && module<l && autstr[module]=='X')
riga.add("X");
else
riga.add(" ");
riga.add(module);
}
enable_aut();
sf.force_update();
}
void TSet_users::build_tree(const TRectype* r)
{
_tree->properties().destroy();
if (r)
{
TToken_string prop_field(r->get(USR_PERMISSION), '\n');
TToken_string pro("",SAFE_PIPE_CHR),row("",SAFE_PIPE_CHR);
TString app;
FOR_EACH_TOKEN(prop_field, tok)
{
pro = tok;
pro.get(0, app);
app.trim();
if (!app.empty())
{
TString_array& prop = _tree->properties(app);
row = pro.get(1);
row.add(pro.get());
row.add(pro.get());
prop.add(row);
}
}
}
}
// mostra le abilitazioni
void TSet_user_passwd::enable_aut()
{
const bool superuser = _msk->get(F_USER) == dongle().administrator();
const int uns = _im->unassigned();
TSheet_field& sf = sheet_field();
const int itms = sf.items();
for (int i = 0; i < itms; i++)
{
const int module = _im->get_module_by_order(i+uns);
TToken_string& riga = sf.row(i);
if (module == BAAUT)
{
sf.disable_cell(i,1);
riga.add("X",1);
}
else
{
const bool on = !superuser && has_module(module, CHK_DONGLE);
sf.enable_cell(i,1,on);
if (superuser)
riga.add("X",1);
}
}
}
bool TSet_user_passwd::user_has_module(int mod)
{
bool yes = mod <= 0;
if (!yes)
{
const int idx = _im->get_index(mod);
if (idx >= 0)
{
TSheet_field& sf = sheet_field();
yes = *sf.cell(idx, 1) > ' ';
}
}
return yes;
}
bool TSet_users::k_notify(TSheet_field& f, int r, KEY k)
{
if (k == K_INS || k == K_DEL)
return false;
if (k == K_TAB)
{
TMask& m = f.sheet_mask();
m.enable(F_ENABLE, f.cell_enabled(r, f.cid2index(F_ENABLE)));
}
return true;
}
bool TSet_user_passwd::user_create()
{
const bool superuser = user() == dongle().administrator();
_rel = new TRelation(LF_USER);
_im = new TInformazione_moduli;
_msk = new TMask("ba1400a") ;
_msk->first_focus(F_USER);
_msk->set_handler(F_PASSWORD, password_handler);
sheet_field().enable(superuser);
_msk->enable_page(1, superuser);
_msk->enable(-G_SUPERUSER, superuser);
return true;
}
bool TSet_users::user_create()
{
TSet_user_passwd::user_create();
_msk->set_handler(F_USER, user_handler);
_msk->set_handler(F_GROUPNAME, group_handler);
TSheet_field& sf = sheet_field();
sf.set_notify(k_notify);
const char* menuname = "bamenu.men";
_tree = new TMenu(menuname);
_msk->set_handler(F_PERMESSI, tree_handler);
_msk->tfield(F_PERMESSI).set_tree(_tree);
_msk->sfield(F_PROPERTIES).set_notify(p_notify);
return true;
}
int TSet_users::read(TMask& m)
{
const int err = TSet_user_passwd::read(m);
if (err == NOERR)
{
const TRectype& r = get_relation()->curr();
build_tree(&r);
TConfig ini(CONFIG_STUDIO, "Main");
m.set(F_PWDMIN, ini.get("MinPwdLen"));
m.set(F_PWDSCAD, ini.get("PasswordExpiration"));
}
return err;
}
void TSet_user_passwd::put_in_record(const TMask& m)
{
TRectype& r = get_relation()->curr();
const char* s = encode(m.get(F_PASSWORD));
if (r.get(USR_PASSWORD) != s)
{
r.put(USR_PASSWORD, s);
if (r.exist(USR_DATAPWD))
{
const TDate oggi(TODAY);
((TMask&)m).set(F_DATAPWD, oggi);
r.put(USR_DATAPWD, oggi);
}
}
}
void TSet_users::put_in_record(const TMask& m)
{
TSet_user_passwd::put_in_record(m);
TString autstr(ENDAUT, ' ');
TSheet_field& sf = sheet_field();
FOR_EACH_SHEET_ROW(sf, i, riga)
{
const char c = riga->get_char(1);
if (c == 'X')
{
const int module = riga->get_int();
autstr[module] = c;
}
}
TRectype& r = get_relation()->curr();
r.put(USR_AUTSTR, autstr);
TToken_string prop_field(256, '\n');
TAssoc_array& prop = _tree->properties();
TString prg;
FOR_EACH_ASSOC_OBJECT(prop, hash, key, obj)
{
TString_array& arr = *(TString_array*)obj;
prg = key;
prg << m.sfield(F_PROPERTIES).separator();
FOR_EACH_ARRAY_ROW(arr, i, row)
{
row->insert(prg, 0);
prop_field.add(*row);
}
}
r.put(USR_PERMISSION, prop_field);
TConfig ini(CONFIG_STUDIO, "Main");
ini.set("MinPwdLen", m.get(F_PWDMIN));
ini.set("PasswordExpiration", m.get(F_PWDSCAD));
}
int TSet_user_passwd::write(const TMask& m)
{
put_in_record(m);
return TRelation_application::write(m);
}
int TSet_user_passwd::rewrite(const TMask& m)
{
put_in_record(m);
return TRelation_application::rewrite(m);
}
bool TSet_users::remove()
{
const TString16 u = get_relation()->curr().get(USR_USERNAME);
const bool ok = TRelation_application::remove();
if (ok && u.full())
{
TFilename file = firm2dir(-1); // Directory dati
file.add("config"); // Directory configurazioni
file.add(u); // Nome utente
file.ext("ini"); // Estensione
file.fremove();
}
return ok;
}
bool TSet_user_passwd::user_destroy()
{
if (_msk != NULL) delete _msk;
if (_rel != NULL) delete _rel;
if (_im != NULL) delete _im;
return true;
}
bool TSet_users::user_destroy()
{
TSet_user_passwd::user_destroy();
if (_tree != NULL)
delete _tree;
return true;
}
int TSet_user_passwd::read(TMask& m)
{
const int err = TRelation_application::read(m);
if (err == NOERR)
{
const TRectype& r = get_relation()->curr();
build_sheet(&r);
const char* pwd = decode(r.get(USR_PASSWORD));
m.set(F_PASSWORD, pwd);
m.set(F_PROVA, pwd);
const int pe = ini_get_int(CONFIG_STUDIO, "Main", "PasswordExpiration");
if (pe > 0)
{
TDate data(m.get(F_DATAPWD));
if (data.ok())
{
data += pe;
m.set(F_DATASCAD, data);
}
}
}
return err;
}
void TSet_user_passwd::init_query_mode(TMask& m)
{
enable_aut();
_msk->set(F_USER,user());
_msk->send_key(K_AUTO_ENTER,0);
_msk->disable(DLG_NEWREC);
_msk->disable(DLG_FINDREC);
_msk->disable(DLG_DELREC);
}
void TSet_user_passwd::init_modify_mode(TMask& m)
{
enable_aut();
_msk->disable(DLG_NEWREC);
_msk->disable(DLG_FINDREC);
_msk->disable(DLG_DELREC);
_msk->enable_page(1, false);
}
int ba1400(int argc, char** argv)
{
if (user() == ::dongle().administrator())
{
TSet_users a;
a.run(argc, argv, TR("Configurazione utenti"));
}
else
{
TSet_user_passwd a;
a.run(argc, argv, TR("Configurazione utente"));
}
return 0;
}