1090 lines
24 KiB
C++
Executable File
1090 lines
24 KiB
C++
Executable File
#include <applicat.h>
|
||
#include <config.h>
|
||
#include <expr.h>
|
||
#include <golem.h>
|
||
#include <netsock.h>
|
||
#include <odbcrset.h>
|
||
#include <progind.h>
|
||
#include <recarray.h>
|
||
#include <relation.h>
|
||
#include <scanner.h>
|
||
#include <transaction.h>
|
||
#include <utility.h>
|
||
#include <xml.h>
|
||
|
||
#include <user.h>
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TRecipient
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TRecipient : public TObject
|
||
{
|
||
TString _address;
|
||
TString _group;
|
||
TString _expr;
|
||
TString _files;
|
||
|
||
public:
|
||
const TString& address() const { return _address; }
|
||
const TString& group() const { return _group; }
|
||
const TString& files() const { return _files; }
|
||
void add_expr(char op, const TString& expr);
|
||
bool can_receive(const TRectype& rec) const;
|
||
void add_files(const TString& files) { _files = files; }
|
||
|
||
virtual bool ok() const
|
||
{ return _address.not_empty() && _expr.not_empty(); }
|
||
|
||
TRecipient(const TToken_string& str);
|
||
virtual ~TRecipient() { }
|
||
};
|
||
|
||
TRecipient::TRecipient(const TToken_string& str)
|
||
{
|
||
str.get(0, _address);
|
||
str.get(1, _group);
|
||
}
|
||
|
||
void TRecipient::add_expr(char op, const TString& expr)
|
||
{
|
||
if (_expr.not_empty())
|
||
_expr << (op == 'A' ? "&&" : "||");
|
||
|
||
if (expr.blank())
|
||
_expr << 1;
|
||
else
|
||
_expr << '(' << expr << ')';
|
||
|
||
}
|
||
|
||
bool TRecipient::can_receive(const TRectype& rec) const
|
||
{
|
||
TExpression e(_expr, _strexpr, TRUE);
|
||
TString val;
|
||
|
||
for (int v = 0; v < e.numvar(); v++)
|
||
{
|
||
const TFixed_string name(e.varname(v));
|
||
|
||
val.cut(0);
|
||
if (rec.exist(name))
|
||
val = rec.get(name);
|
||
else
|
||
{
|
||
|
||
const TFieldref f(name, 0);
|
||
const int logicnum = table2logic(f.id());
|
||
|
||
if (logicnum > 0 && logicnum != rec.num())
|
||
{
|
||
TToken_string & rel = prefix().get_relation(rec.num(), logicnum);
|
||
if (rel.full())
|
||
{
|
||
TToken_string key;
|
||
FOR_EACH_TOKEN(rel, tok)
|
||
key.add(rec.get(tok));
|
||
const TRectype & joined_rec = cache().get(logicnum, key);
|
||
val = f.read(joined_rec);
|
||
}
|
||
}
|
||
else
|
||
val = f.read(rec);
|
||
}
|
||
e.setvar(name, val);
|
||
}
|
||
bool yes = e.as_bool();
|
||
return yes;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TPostman
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TPostman : public TObject
|
||
{
|
||
long _firm;
|
||
int _recipients_lognum;
|
||
TArray _recipient;
|
||
TAssoc_array _expr;
|
||
|
||
protected:
|
||
void test_firm();
|
||
|
||
TRecipient& recipient(int r) const
|
||
{ return (TRecipient&)_recipient[r]; }
|
||
|
||
void add_expr(const TString& addr,
|
||
char op, const TString& expr);
|
||
void add_files(const TString& addr, const TString& files);
|
||
void load_filters();
|
||
|
||
public:
|
||
bool can_dispatch_transaction(const TRectype& rec);
|
||
bool dispatch_transaction(const TRectype& rec,
|
||
const TFilename& name);
|
||
|
||
TExpression* get_filter_expr(const char* flt);
|
||
const char* get_filter(const char* flt);
|
||
bool user_can(const char* flt, const TRelation* rel);
|
||
|
||
TPostman();
|
||
virtual ~TPostman() { }
|
||
};
|
||
|
||
void TPostman::test_firm()
|
||
{
|
||
const long firm = prefix().get_codditta();
|
||
if (firm != _firm)
|
||
{
|
||
_firm = firm;
|
||
_recipients_lognum = 0;
|
||
_recipient.destroy();
|
||
}
|
||
}
|
||
|
||
void TPostman::add_expr(const TString& addr,
|
||
char op, const TString& expr)
|
||
{
|
||
for (int r = _recipient.last(); r >= 0; r--)
|
||
{
|
||
TRecipient& rec = recipient(r);
|
||
if (rec.address() == addr)
|
||
{
|
||
rec.add_expr(op, expr);
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if (rec.group() == addr)
|
||
rec.add_expr(op, expr);
|
||
}
|
||
}
|
||
}
|
||
|
||
void TPostman::add_files(const TString& addr, const TString& files)
|
||
{
|
||
for (int r = _recipient.last(); r >= 0; r--)
|
||
{
|
||
TRecipient& rec = recipient(r);
|
||
if (rec.address() == addr)
|
||
{
|
||
rec.add_files(files);
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if (rec.group() == addr)
|
||
rec.add_files(files);
|
||
}
|
||
}
|
||
}
|
||
|
||
bool TPostman::can_dispatch_transaction(const TRectype& rec)
|
||
{
|
||
test_firm();
|
||
const int lognum = rec.num();
|
||
if (_recipients_lognum != lognum)
|
||
{
|
||
_recipients_lognum = lognum;
|
||
_recipient.destroy();
|
||
|
||
TConfig cfg(CONFIG_DITTA, "MailTransactions");
|
||
TToken_string str("", '<EFBFBD>');
|
||
TString addr, opr, expr, files;
|
||
|
||
// Costruisce la lista dei destinatari
|
||
for (int r = 0; cfg.exist("Recipient", r); r++)
|
||
{
|
||
str = cfg.get("Recipient", NULL, r);
|
||
expand_sys_vars(str);
|
||
TRecipient* rcp = new TRecipient(str);
|
||
_recipient.add(rcp);
|
||
}
|
||
|
||
// Costruisce i filtri per i destinatari
|
||
for (int f = 0; cfg.exist("Filter", f); f++)
|
||
{
|
||
|
||
str = cfg.get("Filter", NULL, f);
|
||
expand_sys_vars(str);
|
||
str.get(0, addr);
|
||
|
||
const int num = str.get_int(1);
|
||
|
||
if (num != lognum)
|
||
continue;
|
||
str.get(2, opr);
|
||
str.get(3, expr);
|
||
str.get(4, files);
|
||
add_expr(addr, opr[0], expr);
|
||
add_files(addr, files);
|
||
}
|
||
|
||
// Elimina destinatari inutili
|
||
for (int d = _recipient.last(); d >= 0; d--)
|
||
{
|
||
if (!recipient(d).ok())
|
||
_recipient.destroy(d, TRUE);
|
||
}
|
||
}
|
||
return !_recipient.empty();
|
||
}
|
||
|
||
static int write_xml(TConfig& cfg, void* jolly)
|
||
{
|
||
TAssoc_array &vars = cfg.list_variables();
|
||
TXmlItem &item = *(TXmlItem *) jolly;
|
||
TToken_string tag(cfg.get_paragraph(), ',');
|
||
const int logicnum = tag.get_int();
|
||
const char * attr = logicnum > 0 ? "Field" : "Attr";
|
||
int rownum = tag.get_int();
|
||
|
||
if (logicnum > 0)
|
||
tag = "Record";
|
||
TXmlItem & child =item.AddChild(tag);
|
||
if (logicnum > 0)
|
||
{
|
||
child.SetAttr("LogicNumber", logicnum);
|
||
if (logicnum > LF_TAB)
|
||
child.SetAttr("TableName", logic2table(logicnum));
|
||
else
|
||
{
|
||
TString table;
|
||
|
||
FOR_EACH_ASSOC_STRING(vars, hobj, key, val)
|
||
if (logicnum <= LF_TAB && strcmp(key, "COD") == 0)
|
||
{
|
||
table = val;
|
||
break;
|
||
}
|
||
child.SetAttr("TableName", table);
|
||
}
|
||
|
||
if (rownum > 0)
|
||
child.SetAttr("RowNumber", rownum);
|
||
}
|
||
|
||
TString s;
|
||
|
||
FOR_EACH_ASSOC_STRING(vars, hobj, key, val)
|
||
if (val && *val)
|
||
{
|
||
s = val;
|
||
if (s[0] == '"' && s.ends_with("\""))
|
||
{
|
||
s.rtrim(1);
|
||
s.ltrim(1);
|
||
}
|
||
s.trim();
|
||
if (TDate::isdate(s))
|
||
{
|
||
TDate date(s);
|
||
|
||
child.AddSoapInt(attr, date.date2ansi()).SetAttr("Name", key);
|
||
}
|
||
else
|
||
{
|
||
if (real::is_natural(s))
|
||
child.AddSoapInt(attr, atoi(s)).SetAttr("Name", key);
|
||
else
|
||
child.AddSoapString(attr, s).SetAttr("Name", key);
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
typedef enum { db_add, db_update, db_remove } db_op;
|
||
|
||
const TString & table_name(int logicnum)
|
||
{
|
||
TString & name = get_tmp_string();
|
||
const int firm = prefix().get_codditta();
|
||
TDir d(logicnum);
|
||
|
||
if (d.is_firm())
|
||
name << format("%05lda", firm) << '.';
|
||
else
|
||
name << "COM.";
|
||
name << logic2table(logicnum);
|
||
return name;
|
||
}
|
||
|
||
HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * table_name, TTrec & recdef)
|
||
{
|
||
TString sql = "CREATE TABLE [";
|
||
int nfields = recdef.fields();
|
||
|
||
sql << table_name << "](\n";
|
||
for (int i = 0; i < nfields; i++)
|
||
{
|
||
TToken_string def = recdef.fielddef(i);
|
||
TString field(def.get(0));
|
||
TFieldtypes t = (TFieldtypes)def.get_int(1);
|
||
|
||
if (i > 0)
|
||
sql << ", ";
|
||
sql << "[" << field << "] ";
|
||
switch (t)
|
||
{
|
||
case _charfld:
|
||
case _alfafld:
|
||
sql << "VARCHAR(" << def.get_int(2) << ")";
|
||
break;
|
||
case _memofld:
|
||
sql << "VARCHAR(MAX)"; break;
|
||
case _datefld:
|
||
sql << "DATE"; break;
|
||
case _boolfld:
|
||
sql << "BIT DEFAULT 0"; break;
|
||
case _realfld:
|
||
case _wordfld:
|
||
case _intfld:
|
||
case _longfld:
|
||
case _intzerofld:
|
||
case _longzerofld:
|
||
default: sql << "NUMERIC(" << def.get_int(2) << "," << def.get_int(3) << ")"; break;
|
||
}
|
||
|
||
}
|
||
sql << ");\n";
|
||
int err = recset.exec(sql);
|
||
|
||
if (err < 0)
|
||
return false;
|
||
for (int k = 0; k < recdef.keys(); k++)
|
||
{
|
||
TToken_string key(recdef.keydef(k), '+');
|
||
bool dupkeys = false;
|
||
int pos = key.find("|");
|
||
int el = 0;
|
||
|
||
if (pos > 0)
|
||
{
|
||
dupkeys = key.mid(pos + 1).full();
|
||
key = key.left(pos);
|
||
}
|
||
sql = "CREATE ";
|
||
sql << (dupkeys ? "INDEX KEY" : "UNIQUE INDEX KEY") << k + 1 << " ON [" << table_name << "] (";
|
||
|
||
FOR_EACH_STR_TOKEN(key, field)
|
||
{
|
||
if (el++ > 0)
|
||
sql << ',';
|
||
if (field.starts_with("UPPER"))
|
||
{
|
||
field = field.mid(6, field.len() - 7);
|
||
sql << field << "_UPPER";
|
||
TString alter = "ALTER TABLE [";
|
||
|
||
alter << table_name << "] ADD " << field << "_UPPER AS UPPER(" << field << ");";
|
||
err = recset.exec(alter);
|
||
}
|
||
else
|
||
{
|
||
int pos = field.find("[");
|
||
|
||
if (pos > 0)
|
||
{
|
||
TString fld = field.left(pos);
|
||
|
||
sql << fld << "_MID";
|
||
|
||
const int start = atoi(field.mid(pos + 1));
|
||
|
||
pos = field.find(",", pos + 1);
|
||
const int end = pos > 0 ? atoi(field.mid(pos + 1)) : 0;
|
||
|
||
TString alter = "ALTER TABLE [";
|
||
|
||
alter << table_name << "] ADD " << fld << "_MID AS " << (recset.driver() == ODBC_mssql ? "SUBSTRING(" : "MID(") << fld << ',' << start;
|
||
|
||
if (end > 0)
|
||
alter << ',' << end - start + 1;
|
||
alter << ");";
|
||
err = recset.exec(alter);
|
||
}
|
||
else
|
||
sql << field;
|
||
}
|
||
}
|
||
sql << ");\n";
|
||
int err = recset.exec(sql);
|
||
|
||
if (err < 0)
|
||
return false;
|
||
}
|
||
return err >= 0;
|
||
}
|
||
|
||
HIDDEN const TString & build_statement(const db_op op, int logicnum, const char * table_name, const TString_array & keys, const TString_array & values)
|
||
{
|
||
TString & statement = get_tmp_string();
|
||
|
||
if (op == db_add)
|
||
{
|
||
statement << "INSERT INTO [" << table_name << "] (";
|
||
FOR_EACH_ARRAY_ROW(values, r, row)
|
||
{
|
||
if (r > 0)
|
||
statement << ", ";
|
||
statement << row->get(0);
|
||
}
|
||
statement << ") VALUES (";
|
||
FOR_EACH_ARRAY_ROW(values, rk, rowk)
|
||
{
|
||
if (rk > 0)
|
||
statement << ", ";
|
||
statement << rowk->get(1);
|
||
}
|
||
statement << ')';
|
||
}
|
||
else
|
||
if (op == db_update)
|
||
{
|
||
statement << "UPDATE [" << table_name << "] SET ";
|
||
FOR_EACH_ARRAY_ROW(values, r, row)
|
||
{
|
||
if (r > 0)
|
||
statement << ", ";
|
||
statement << *row;
|
||
}
|
||
statement << " WHERE";
|
||
FOR_EACH_ARRAY_ROW(keys, rk, rowk)
|
||
{
|
||
if (rk > 0)
|
||
statement << " AND";
|
||
statement << ' ' << *rowk;
|
||
}
|
||
}
|
||
else
|
||
if (op == db_remove)
|
||
{
|
||
statement << "DELETE FROM [" << table_name << "] WHERE ";
|
||
FOR_EACH_ARRAY_ROW(keys, rk, rowk)
|
||
{
|
||
if (rk > 0)
|
||
statement << " AND";
|
||
statement << ' ' << *rowk;
|
||
}
|
||
}
|
||
statement << ';';
|
||
return statement;
|
||
}
|
||
|
||
HIDDEN const char * make_val(const char * fld, TFieldtypes t, TString &src)
|
||
{
|
||
TString & val = get_tmp_string();
|
||
int pos = src.find("'");
|
||
|
||
val << fld << '=';
|
||
while (pos > 0)
|
||
{
|
||
src.insert("'", pos);
|
||
pos = src.find("'", pos + 2);
|
||
}
|
||
switch (t)
|
||
{
|
||
case _alfafld:
|
||
case _charfld:
|
||
case _datefld:
|
||
case _memofld:
|
||
val << '\'' << src << '\'';
|
||
break;
|
||
case _intfld:
|
||
case _longfld:
|
||
case _realfld:
|
||
case _wordfld:
|
||
case _intzerofld:
|
||
case _longzerofld:
|
||
val << (src.blank() ? "0" : src);
|
||
break;
|
||
case _boolfld:
|
||
val << (src.blank() ? "'FALSE'" : "'TRUE'");
|
||
break;
|
||
default:
|
||
val << src;
|
||
break;
|
||
}
|
||
return val;
|
||
}
|
||
HIDDEN bool popolate_table(TODBC_recordset & recset, int logicnum, const char * table_name, TTrec & recdef)
|
||
{
|
||
bool ok = false;
|
||
int nfields = recdef.fields();
|
||
TCursor c(new TRelation(logicnum));
|
||
const long items = c.items();
|
||
TProgress_monitor pi(items, format(TR("caricamento tabella %s"), table_name));
|
||
|
||
for (c.pos() = 0; pi.addstatus() && c.pos() < items; ++c)
|
||
{
|
||
TString_array values;
|
||
TString_array keys;
|
||
|
||
for (int i = 0; i < nfields; i++)
|
||
{
|
||
TToken_string def = recdef.fielddef(i);
|
||
TString field(def.get(0));
|
||
TFieldtypes t = (TFieldtypes)def.get_int(1);
|
||
TString str = c.curr().get(field);
|
||
TToken_string row(make_val(field, t, str), '=');
|
||
|
||
values.add(row);
|
||
}
|
||
|
||
TToken_string key(recdef.keydef(), '+');
|
||
int pos = key.find("|");
|
||
|
||
if (pos > 0)
|
||
key = key.left(pos);
|
||
FOR_EACH_STR_TOKEN(key, field)
|
||
{
|
||
TString fld = field;
|
||
int pos = fld.find("[");
|
||
|
||
if (pos > 0)
|
||
fld = fld.left(pos);
|
||
|
||
TToken_string def = recdef.fielddef(recdef.field(fld));
|
||
TFieldtypes t = (TFieldtypes)def.get_int(1);
|
||
TString str = c.curr().get(fld);
|
||
|
||
if (pos > 0)
|
||
{
|
||
int start = atoi(field.mid(pos));
|
||
|
||
pos = field.find(',', pos);
|
||
str = str.smid(start, pos > 0 ? pos : 0);
|
||
}
|
||
|
||
TToken_string row(make_val(field, t, str), '=');
|
||
|
||
keys.add(row);
|
||
}
|
||
|
||
const TString & statement = build_statement(db_add, logicnum, table_name, keys, values);
|
||
int err = recset.exec(statement);
|
||
|
||
if (err <= 0)
|
||
{
|
||
const TString & statement = build_statement( db_update, logicnum, table_name, keys, values);
|
||
|
||
err = recset.exec(statement);
|
||
}
|
||
if (err <= 0)
|
||
error_box(FR("Errore n. %d invio file %d"), -err, logicnum);
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_files, const TFilename & name)
|
||
{
|
||
TODBC_recordset recset;
|
||
TToken_string odbc_str(dsn.mid(5), ',');
|
||
TString_array files;
|
||
TString_array keys;
|
||
TString_array values;
|
||
TConfig ini(name); ini.set_paragraph("Transaction");
|
||
TString tr_type = ini.get("Action"); tr_type.upper();
|
||
TString main_file;
|
||
|
||
main_file << num;
|
||
db_op op = db_add;
|
||
|
||
odbc_str.rtrim(1);
|
||
if (tr_type == TRANSACTION_INSERT)
|
||
op = db_add;
|
||
else
|
||
if (tr_type == TRANSACTION_MODIFY)
|
||
op = db_update;
|
||
else
|
||
if (tr_type == TRANSACTION_DELETE)
|
||
op = db_remove;
|
||
if (!recset.connect(odbc_str.get(0), odbc_str.get(1), odbc_str.get(2)))
|
||
{
|
||
error_box(FR("Non posso connettermi a (%s)"), (const char *)odbc_str);
|
||
return;
|
||
}
|
||
ini.list_paragraphs(files);
|
||
FOR_EACH_ARRAY_ROW(files, i, row)
|
||
{
|
||
TString curr_file = *row;
|
||
const int pos = curr_file.find(",");
|
||
TToken_string rowkey("", ',');
|
||
|
||
if (pos > 0)
|
||
{
|
||
rowkey = curr_file.mid(pos + 1);
|
||
curr_file = curr_file.left(pos);
|
||
}
|
||
|
||
int curr_file_num = atoi(curr_file);
|
||
const bool to_elab = (curr_file_num > 0) && (elab_files.blank() || elab_files.find(curr_file) >= 0);
|
||
|
||
if (to_elab)
|
||
{
|
||
keys.destroy();
|
||
values.destroy();
|
||
ini.set_paragraph(*row);
|
||
TTrec wrk(curr_file_num);
|
||
int nfields = wrk.fields();
|
||
const TString name = table_name(curr_file_num);
|
||
|
||
/*TString check_statement = "SELECT TOP 1 * FROM [";
|
||
|
||
check_statement << name << "];";*/
|
||
|
||
TString check_statement = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '";
|
||
|
||
check_statement << name << "';";
|
||
int err = recset.exec(check_statement);
|
||
if (err <= 0)
|
||
{
|
||
create_table(recset, curr_file_num, name, wrk);
|
||
popolate_table(recset, curr_file_num, name, wrk);
|
||
recset.exec("COMMIT;");
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < nfields; i++)
|
||
{
|
||
TToken_string def = wrk.fielddef(i);
|
||
TString field(def.get(0));
|
||
TFieldtypes t = (TFieldtypes)def.get_int(1);
|
||
TString str = ini.get(field);
|
||
str = str.strip("\"");
|
||
TToken_string row(make_val(field, t, str), '=');
|
||
|
||
values.add(row);
|
||
}
|
||
|
||
TToken_string key(wrk.keydef(), '+');
|
||
int pos = key.find("|");
|
||
|
||
if (pos > 0)
|
||
key = key.left(pos);
|
||
pos = 0;
|
||
FOR_EACH_STR_TOKEN(key, field)
|
||
{
|
||
TString fld = field;
|
||
|
||
if (fld.starts_with("UPPER"))
|
||
{
|
||
fld = fld.smid(7);
|
||
fld.rtrim(1);
|
||
fld << "_UPPER";
|
||
}
|
||
else
|
||
{
|
||
pos = fld.find("[");
|
||
|
||
if (pos > 0)
|
||
fld = fld.left(pos);
|
||
}
|
||
|
||
TString str = ini.get(field);
|
||
|
||
if (str.blank())
|
||
{
|
||
ini.set_paragraph(main_file);
|
||
str = ini.get(fld);
|
||
if (str.blank())
|
||
str << rowkey.get();
|
||
ini.set_paragraph(*row);
|
||
}
|
||
str = str.strip("\"");
|
||
|
||
TToken_string def = wrk.fielddef(wrk.field(fld));
|
||
TFieldtypes t = (TFieldtypes)def.get_int(1);
|
||
|
||
if (pos > 0)
|
||
{
|
||
int start = atoi(field.mid(pos + 1));
|
||
|
||
pos = field.find(',', pos + 1);
|
||
str = str.smid(start, pos > 0 ? atoi(field.mid(pos + 1)) : 0);
|
||
fld << "_MID";
|
||
}
|
||
|
||
TToken_string row(make_val(fld, t, str), '=');
|
||
keys.add(row);
|
||
}
|
||
const TString & statement = build_statement(op, curr_file_num, name, keys, values);
|
||
int err = recset.exec(statement);
|
||
|
||
if (op < db_remove && err <= 0)
|
||
{
|
||
const TString & statement = build_statement(op == db_add ? db_update : db_add, curr_file_num, name, keys, values);
|
||
|
||
err = recset.exec(statement);
|
||
}
|
||
if (err <= 0)
|
||
error_box(FR("Errore n. %d invio file %d"), -err, curr_file_num);
|
||
else
|
||
recset.exec("COMMIT;");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
bool TPostman::dispatch_transaction(const TRectype& rec,
|
||
const TFilename& name)
|
||
{
|
||
bool ok = can_dispatch_transaction(rec);
|
||
if (ok)
|
||
{
|
||
TToken_string dest;
|
||
TToken_string file_dest;
|
||
TToken_string soap_dest;
|
||
TToken_string odbc_dest;
|
||
TToken_string odbc_files;
|
||
TString last_error;
|
||
|
||
for (int r = 0; r < _recipient.items(); r++)
|
||
{
|
||
const TRecipient& a = recipient(r);
|
||
if (a.can_receive(rec))
|
||
{
|
||
TString addr = a.address();
|
||
if (addr.starts_with("http")) // Indirizzo http
|
||
soap_dest.add(addr); else
|
||
if (addr.find('@') > 0) // Indirizzo posta
|
||
dest.add(addr);
|
||
else
|
||
{
|
||
if (fexist(addr))
|
||
file_dest.add(addr);
|
||
else
|
||
if (addr.starts_with("ODBC"))
|
||
{
|
||
if (addr.mid(4).blank())
|
||
addr << '(' << ini_get_string(CONFIG_DITTA, "MailTransactions", "ODBCDSN")
|
||
<< ',' << ini_get_string(CONFIG_DITTA, "MailTransactions", "ODBCUser")
|
||
<< ',' << decode(ini_get_string(CONFIG_DITTA, "MailTransactions", "ODBCPassword")) << ')';
|
||
odbc_dest.add(addr);
|
||
odbc_files.add(a.files());
|
||
}
|
||
else
|
||
{
|
||
if (addr != last_error)
|
||
{
|
||
ok = error_box(FR("Non esiste la cartella di destinazione %s"), (const char*)addr);
|
||
last_error = addr;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (dest.items() > 0)
|
||
{
|
||
TMail_message msg(dest.get(0));
|
||
for (const char* r = dest.get(1); r; r = dest.get())
|
||
msg.add_copy_recipient(r);
|
||
|
||
TString16 subject;
|
||
switch (rec.num())
|
||
{
|
||
case LF_TAB:
|
||
case LF_TABCOM:
|
||
case LF_TABGEN:
|
||
subject << rec.get("COD");
|
||
break;
|
||
case LF_TABMOD:
|
||
subject << '&' << rec.get("COD");
|
||
break;
|
||
default:
|
||
subject << rec.num();
|
||
break;
|
||
}
|
||
msg.set_subject(subject);
|
||
|
||
TScanner trans(name);
|
||
while (trans.good())
|
||
{
|
||
TString& line = trans.line();
|
||
msg.add_line(line);
|
||
}
|
||
ok = msg.send(TRUE);
|
||
}
|
||
|
||
if (file_dest.items() > 0)
|
||
{
|
||
TString16 basename;
|
||
const struct tm* tl = xvt_time_now();
|
||
basename.format("%02d%02d%02d_%02d%02d%02d_0",
|
||
tl->tm_year%100, tl->tm_mon+1, tl->tm_mday,
|
||
tl->tm_hour, tl->tm_min, tl->tm_sec);
|
||
|
||
FOR_EACH_TOKEN(file_dest, r)
|
||
{
|
||
TFilename output;
|
||
int retry = 0;
|
||
for (retry = 0; retry < 10; retry++) // Per ora tento solo 10 volte
|
||
{
|
||
output = r;
|
||
output.add(basename);
|
||
output << retry << ".ini";
|
||
if (!output.exist()) // Ho generato un nome buono
|
||
break;
|
||
}
|
||
if (retry >= 10)
|
||
ok = false;
|
||
else
|
||
ok = fcopy(name, output);
|
||
}
|
||
}
|
||
|
||
if (soap_dest.items() > 0)
|
||
{
|
||
TConfig trans(name);
|
||
TXmlItem item;
|
||
TSocketClient socket;
|
||
char * buf = new char[1024 * 256];
|
||
|
||
#ifdef WIN32
|
||
ostrstream stream(buf, 1024 * 256);
|
||
#else
|
||
ostringstream stream(buf);
|
||
#endif
|
||
|
||
bool ok = true;
|
||
|
||
item.SetTag("m:CampoTransaction");
|
||
trans.for_each_paragraph(write_xml, &item);
|
||
|
||
item.Write(stream, 2);
|
||
stream << '\0';
|
||
|
||
#ifdef DBG
|
||
TFilename name;
|
||
char hostname[256];
|
||
int len = strlen(buf);
|
||
|
||
len += 79;
|
||
xvt_sys_get_host_name(hostname, sizeof(hostname));
|
||
|
||
name.temp();
|
||
|
||
ofstream f(name);
|
||
|
||
f << "POST / HTTP/1.1\n"
|
||
<< "User-Agent: Campo\n"
|
||
<< "Host: " << hostname << "\n"
|
||
<< "Content-Type: text/xml; charset=utf-8\n"
|
||
<< "Content-length: " << len << "\n"
|
||
<< "SOAPAction: \"/\"\r\n\r\n"
|
||
<< "<SOAP-ENV:Envelope>\n<SOAP-ENV:Body>\r\n";
|
||
|
||
item.Write(f, 2);
|
||
|
||
f << "\n</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\r\n\r\n";
|
||
#endif
|
||
|
||
FOR_EACH_TOKEN(soap_dest, r)
|
||
{
|
||
CONNID id = socket.QueryConnection("", r);
|
||
socket.HttpSoap(id, buf);
|
||
}
|
||
}
|
||
|
||
if (odbc_dest.items() > 0)
|
||
{
|
||
odbc_files.restart();
|
||
FOR_EACH_TOKEN(odbc_dest, r)
|
||
{
|
||
const TString & dsn = r;
|
||
|
||
TAuto_token_string files = odbc_files.get();
|
||
|
||
|
||
::odbc_send(dsn, rec.num(), files, name);
|
||
}
|
||
remove_file(name);
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
void TPostman::load_filters()
|
||
{
|
||
TToken_string perm(4096, '\n');
|
||
TAuto_token_string row(80);
|
||
|
||
// Costruisce il nome dell'applicazione principale
|
||
const TApplication& ma = main_app();
|
||
TFilename app(ma.argv(0));
|
||
app = app.name_only();
|
||
|
||
for (int a = 1; a < ma.argc(); a++)
|
||
{
|
||
row = ma.argv(a); row.upper();
|
||
if (row[0] != '/' && row[1] != 'I')
|
||
app << ' ' << row;
|
||
else
|
||
break;
|
||
}
|
||
|
||
// Stringhe delle espressioni i filtro
|
||
TAssoc_array expr;
|
||
|
||
// Scandisce l'albero degli utenti/gruppi
|
||
const TString_array& uag = user_and_groups();
|
||
FOR_EACH_ARRAY_ROW(uag, r, rec)
|
||
{
|
||
perm = rec->after(rec->separator()); // Permessi del nodo corrente
|
||
if (!perm.blank())
|
||
{
|
||
FOR_EACH_TOKEN(perm, tok)
|
||
{
|
||
row = tok;
|
||
const TString80 appmod = row.get(0);
|
||
const bool is_mod = appmod.len() == 2;
|
||
// Il programma oppure il modulo corrispondono
|
||
if ((is_mod && app.compare(appmod, 2, TRUE) == 0) ||
|
||
app.compare(appmod, -1, TRUE) == 0)
|
||
{
|
||
TString80 key = row.get(2); key.trim(); // Tipo di filtro
|
||
row = row.get(); row.trim(); // Espressione di filtro
|
||
if (key.not_empty() && row.not_empty() && row != "1")
|
||
{
|
||
key.upper();
|
||
TString* str = (TString*)expr.objptr(key);
|
||
if (str == NULL)
|
||
{
|
||
str = new TString(row); // Crea una nuova stringa
|
||
expr.add(key, str);
|
||
}
|
||
else
|
||
{ // Somma alla stringa precendente
|
||
if (*str != "0") // Se sono FALSE lasciami stare
|
||
{
|
||
if (row != "0") // Se aggiungo qualcosa di non ovvio
|
||
{
|
||
str->insert("(", 0);
|
||
*str << ")AND(";
|
||
*str << row << ')';
|
||
}
|
||
else
|
||
*str = "0";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Trasforma le stringhe in espressioni
|
||
FOR_EACH_ASSOC_STRING(expr, hash, key, str)
|
||
{
|
||
TExpression* e = new TExpression(str, _strexpr, TRUE);
|
||
_expr.add(key, e);
|
||
}
|
||
|
||
// Inserisce un elemento fasullo per segnalare l'avvenuta lettura
|
||
if (_expr.items() == 0)
|
||
_expr.add("", new TObject);
|
||
}
|
||
|
||
TExpression* TPostman::get_filter_expr(const char* flt)
|
||
{
|
||
if (_expr.items() == 0)
|
||
load_filters();
|
||
TString80 f(flt); f.upper();
|
||
TExpression* e = (TExpression*)_expr.objptr(f);
|
||
return e;
|
||
}
|
||
|
||
const char* TPostman::get_filter(const char* flt)
|
||
{
|
||
TExpression* e = get_filter_expr(flt);
|
||
return e ? e->string() : NULL;
|
||
}
|
||
|
||
bool TPostman::user_can(const char* flt, const TRelation* rel)
|
||
{
|
||
bool yes_he_can = TRUE;
|
||
TExpression* e = get_filter_expr(flt);
|
||
if (e != NULL)
|
||
{
|
||
if (rel != NULL)
|
||
{
|
||
for (int i = e->numvar()-1; i >= 0; i--)
|
||
{
|
||
const TString& name = e->varname(i);
|
||
const TFieldref ref(name, 0);
|
||
const TString& val = ref.read(*rel);
|
||
e->setvar(name, val);
|
||
}
|
||
yes_he_can = e->as_bool();
|
||
}
|
||
else
|
||
{
|
||
if (e->numvar() == 0)
|
||
yes_he_can = e->as_bool();
|
||
}
|
||
}
|
||
return yes_he_can;
|
||
}
|
||
|
||
TPostman::TPostman() : _firm(-1), _recipients_lognum(0)
|
||
{
|
||
}
|
||
|
||
TPostman& postman()
|
||
{
|
||
static TPostman* _postman = NULL;
|
||
if (_postman == NULL)
|
||
_postman = new TPostman;
|
||
return *_postman;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Public interface
|
||
///////////////////////////////////////////////////////////
|
||
|
||
bool can_dispatch_transaction(const TRectype& rec)
|
||
{
|
||
return postman().can_dispatch_transaction(rec);
|
||
}
|
||
|
||
bool dispatch_transaction(const TRectype& rec, const TFilename& name)
|
||
{
|
||
return postman().dispatch_transaction(rec, name);
|
||
}
|
||
|
||
const char* get_user_filter(const char* flt)
|
||
{
|
||
return postman().get_filter(flt);
|
||
}
|
||
|
||
const char* get_user_read_filter()
|
||
{
|
||
return get_user_filter("Lettura");
|
||
}
|
||
|
||
const char* get_user_write_filter()
|
||
{
|
||
return get_user_filter("Scrittura");
|
||
}
|
||
|
||
bool user_can_read(const TRelation* rel)
|
||
{
|
||
return postman().user_can("Lettura", rel);
|
||
}
|
||
|
||
bool user_can_write(const TRelation* rel)
|
||
{
|
||
return user_can_read(rel) && postman().user_can("Scrittura", rel);
|
||
}
|
||
|
||
bool user_can_delete(const TRelation* rel)
|
||
{
|
||
return user_can_write(rel) && postman().user_can("Eliminazione", rel);
|
||
}
|
||
|
||
bool user_can_do(const char* azione, const TRelation* rel)
|
||
{
|
||
return postman().user_can(azione, rel);
|
||
}
|
||
|