3354d8ddac
Files correlati : Ricompilazione Demo : [ ] Commento :ostrstream stream(... per poter compilare git-svn-id: svn://10.65.10.50/trunk@15873 c028cbd2-c16b-5b4b-a496-9718f37d4682
564 lines
12 KiB
C++
Executable File
564 lines
12 KiB
C++
Executable File
#include <applicat.h>
|
|
#include <expr.h>
|
|
#include <golem.h>
|
|
#include <netsock.h>
|
|
#include <recarray.h>
|
|
#include <relation.h>
|
|
#include <scanner.h>
|
|
#include <utility.h>
|
|
#include <xml.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TRecipient
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TRecipient : public TObject
|
|
{
|
|
TString _address;
|
|
TString _group;
|
|
TString _expr;
|
|
|
|
public:
|
|
const TString& address() const { return _address; }
|
|
const TString& group() const { return _group; }
|
|
void add_expr(char op, const TString& expr);
|
|
bool can_receive(const TRectype& rec) const;
|
|
|
|
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);
|
|
for (int v = 0; v < e.numvar(); v++)
|
|
{
|
|
const char* name = e.varname(v);
|
|
if (rec.exist(name))
|
|
e.setvar(name, rec.get(name));
|
|
else
|
|
e.setvar(name, "");
|
|
}
|
|
bool yes = e.as_bool();
|
|
return yes;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TPostman
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TPostman : public TObject
|
|
{
|
|
long _firm;
|
|
bool _recipients_ok;
|
|
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 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_ok = FALSE;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TPostman::can_dispatch_transaction(const TRectype& rec)
|
|
{
|
|
test_firm();
|
|
if (!_recipients_ok)
|
|
{
|
|
_recipients_ok = TRUE;
|
|
_recipient.destroy();
|
|
|
|
TConfig cfg(CONFIG_DITTA, "MailTransactions");
|
|
TAuto_token_string str;
|
|
TString addr, opr, expr;
|
|
|
|
// Costruisce la lista dei destinatari
|
|
for (int r = 0; cfg.exist("Recipient", r); r++)
|
|
{
|
|
str = cfg.get("Recipient", NULL, r);
|
|
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);
|
|
const int num = str.get_int(1);
|
|
if (num != rec.num()) continue;
|
|
|
|
str.get(0, addr);
|
|
str.get(2, opr);
|
|
str.get(3, expr);
|
|
add_expr(addr, opr[0], expr);
|
|
}
|
|
|
|
// Elimina destinatari inutili
|
|
for (int d = _recipient.last(); d >= 0; d--)
|
|
{
|
|
if (!recipient(d).ok())
|
|
_recipient.destroy(d, TRUE);
|
|
}
|
|
}
|
|
return _recipient.items() > 0;
|
|
}
|
|
|
|
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);
|
|
child.SetAttr("TableName", logic2table(logicnum));
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
TString last_error;
|
|
|
|
for (int r = 0; r < _recipient.items(); r++)
|
|
{
|
|
const TRecipient& a = recipient(r);
|
|
if (a.can_receive(rec))
|
|
{
|
|
const TString& addr = a.address();
|
|
if (addr.find('@') >= 0) // Indirizzo posta
|
|
dest.add(addr);
|
|
if (addr.starts_with("http")) // Indirizzo http
|
|
soap_dest.add(addr);
|
|
else
|
|
{
|
|
if (fexist(addr))
|
|
file_dest.add(addr);
|
|
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;
|
|
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;
|
|
time_t lt; time(<);
|
|
struct tm * tl = localtime(<);
|
|
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("Campo");
|
|
trans.for_each_paragraph(write_xml, &item);
|
|
|
|
item.Write(stream, 0);
|
|
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>\n";
|
|
|
|
item.Write(f, 0);
|
|
|
|
f << "\n</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\r\n";
|
|
#endif
|
|
|
|
FOR_EACH_TOKEN(soap_dest, r)
|
|
{
|
|
CONNID id = socket.QueryConnection("", r);
|
|
socket.HttpSoap(id, buf);
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void TPostman::load_filters()
|
|
{
|
|
TRecord_cache users(LF_USER);
|
|
|
|
TToken_string perm(4096, '\n');
|
|
TAuto_token_string row(80);
|
|
|
|
// Costruisce il nome dell'applicazione principale
|
|
TFilename app(main_app().argv(0));
|
|
app.ext("");
|
|
app = app.name();
|
|
|
|
for (int a = 1; a < main_app().argc(); a++)
|
|
{
|
|
row = main_app().argv(a);
|
|
if (row[0] != '/')
|
|
app << ' ' << row;
|
|
else
|
|
break;
|
|
}
|
|
|
|
// Stringhe delle espressioni i filtro
|
|
TAssoc_array expr;
|
|
|
|
// Scandisce l'albero degli utenti/gruppi
|
|
for (TString16 u = user(); u.not_empty() && !users.already_loaded(u); )
|
|
{
|
|
const TRectype& urec = users.get(u);
|
|
|
|
// Test di validita'del record da eseguire solo la prima volta
|
|
if (u == user() && !urec.exist("PERMISSION"))
|
|
break;
|
|
perm = urec.get("PERMISSION"); // 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";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
u = urec.get("GROUPNAME");
|
|
}
|
|
|
|
// 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("", NULL);
|
|
}
|
|
|
|
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_ok(FALSE)
|
|
{
|
|
}
|
|
|
|
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);
|
|
}
|
|
|