diff --git a/ba/ba1100.cpp b/ba/ba1100.cpp index 38ccf8fb9..34ba50753 100755 --- a/ba/ba1100.cpp +++ b/ba/ba1100.cpp @@ -1,7 +1,7 @@ #ifdef WIN32 #define _CRT_NONSTDC_NO_DEPRECATE 1 #define _CRT_SECURE_NO_WARNINGS 1 -#include + #include #include #else #include @@ -431,7 +431,7 @@ void TManutenzione_app::insert_riga (long riga_sel, TToken_string& riga) _mask->disable(DLG_RECORD); _mask->disable(DLG_LOAD); _mask->disable(DLG_DUMP); - _mask->show(F_TAB, logicnum >= LF_TABGEN && logicnum <= LF_TAB); + _mask->show(F_TAB, (logicnum >= LF_TABGEN && logicnum <= LF_TAB)||(logicnum == LF_TABMOD)); _mask->hide(FLD_EXTEND); _mask->hide(FLD_EOX); _mask->set (FLD_NUM, riga.get(0)); @@ -596,9 +596,6 @@ void TManutenzione_app::edit_riga (const TString& name) void TManutenzione_app::edit_riga (long riga_sel, TToken_string& riga) { - KEY tasto; - FileDes dep; - TDir d; const int logicnum = int(riga_sel) + 1; _mask->enable(DLG_PACK, _superprassi); @@ -627,8 +624,8 @@ void TManutenzione_app::edit_riga (long riga_sel, TToken_string& riga) _mask->show(FLD_EXTEND, enable_extend); _mask->show(FLD_EOX, enable_extend); - tasto = _mask->run(); + KEY tasto = _mask->run(); switch (tasto) { case K_F4: @@ -651,6 +648,7 @@ void TManutenzione_app::edit_riga (long riga_sel, TToken_string& riga) case K_F7: case K_ENTER: { + FileDes dep; strncpy (dep.SysName,_mask->get(FLD_NOME), sizeof(dep.SysName)); dep.EOD = atol(_mask->get (FLD_EOD)); dep.Flags = atol(_mask->get (FLD_FLAG)); @@ -668,7 +666,7 @@ void TManutenzione_app::edit_riga (long riga_sel, TToken_string& riga) if (eox != oldeox) { - d.get(logicnum); + TDir d; d.get(logicnum); TFilename f_name(d.name()); f_name.ext("dbf"); @@ -835,11 +833,6 @@ bool TManutenzione_app::moveable_file(int file) const void TManutenzione_app::update_dir() { - // Particolare significato dei flags oltre i 10000: - // trattasi di files PRASSI, (ad esempio i cespiti) che da noi non vengono toccati, - // in modo da evitare colpe inutili. Noi aggiorniamo solo i tracciati su dir e trc, - // ma il file fisico manco lo tocchiamo!! - if (prefix().get_codditta() <= _history_firm) return; @@ -1181,10 +1174,10 @@ void TManutenzione_app::convert_dir() s << TR("ditta ") << atol (pref); s << ".\n"; - TProgind p(update_items ? update_items : 1, s, is_power_station()); + TProgress_monitor p(update_items ? update_items : 1, s, is_power_station()); for (int i = LF_USER; i <= update_items; i++) { - if (!p.addstatus(1)) + if (!p.add_status()) break; const TTrec& rs = (const TTrec&)_recs[i]; // Nuovo tracciato record diff --git a/ba/ba1100.h b/ba/ba1100.h index 14cce4435..cfb2d880c 100755 --- a/ba/ba1100.h +++ b/ba/ba1100.h @@ -43,8 +43,7 @@ public: void add(); void rebuild() { _items = _dir.items();} - TDir_sheet(const char* title, bool superprassi, const char* col = "N.@3R|Nome@20|EOD@7R|EOX@7R|Lung.@7R|Descrizione@43|Formula@33|Flags@7R"); - virtual ~TDir_sheet(); + TDir_sheet(const char* title, bool superprassi); }; class TRec_sheet : public TObject diff --git a/ba/ba1101.cpp b/ba/ba1101.cpp index fec9e9c80..13f0fce03 100755 --- a/ba/ba1101.cpp +++ b/ba/ba1101.cpp @@ -25,8 +25,10 @@ void TDir_sheet::add() _items = nitems; } -TDir_sheet::TDir_sheet(const char* title, bool superprassi, const char* colonne) - : TSheet(0, 0, 0, 0, title, colonne, superprassi ? 0xC : 0x8) +TDir_sheet::TDir_sheet(const char* title, bool superprassi) + : TSheet(0, 0, 0, 0, title, + HR("N.@3R|Nome@20|EOD@7R|EOX@7R|Lung.@7R|Descrizione@43|Formula@33|Flags@7R"), + superprassi ? 0xC : 0x8) { add_button(DLG_PRINT, TR("Tracciati"), K_F3, TOOL_PRINT); add_button(DLG_NULL, "", 0); // Separatore @@ -47,15 +49,11 @@ TDir_sheet::TDir_sheet(const char* title, bool superprassi, const char* colonne) rebuild(); } -TDir_sheet::~TDir_sheet() +void TDir_sheet::get_row(long nrow, TToken_string& l) { -} - -void TDir_sheet::get_row(long n, TToken_string& l) -{ - n++; - _dir.get ((int)n,_nolock,_nordir,_sysdirop); - l.format("%d", n); // Numero progressivo del file + const int logicnum = int(nrow+1); + _dir.get (logicnum,_nolock,_nordir,_sysdirop); + l.format("%d", logicnum); // Numero logico del file l.add(_dir.name()); l.add(_dir.eod()); l.add(_dir.eox()); diff --git a/ba/ba4200.h b/ba/ba4200.h index 69a9e1c45..74eb7a81f 100755 --- a/ba/ba4200.h +++ b/ba/ba4200.h @@ -389,5 +389,7 @@ #define F_DESREG96 414 #define H_TIPOA 415 #define F_CAUSQUA 416 +#define F_CATPAR 417 +#define F_ESCPRECOMP 418 #endif // __BA4200_H diff --git a/ba/ba4200b.uml b/ba/ba4200b.uml index 9f8769828..fd26d88e2 100755 --- a/ba/ba4200b.uml +++ b/ba/ba4200b.uml @@ -850,58 +850,58 @@ PAGE "Pag.5" -1 -1 77 20 GROUPBOX DLG_NULL 78 5 BEGIN -PROMPT 0 0 "Persone fisiche" -FLAGS "R" + PROMPT 0 0 "Persone fisiche" + FLAGS "R" END NUMBER DLG_NULL 5 BEGIN -PROMPT 2 1 "Codice " -FIELD LF_ANAGFIS->CODANAGR -FLAGS "DR" -GROUP 1 + PROMPT 2 1 "Codice " + FIELD LF_ANAGFIS->CODANAGR + FLAGS "DR" + GROUP 1 END STRING DLG_NULL 30 BEGIN -PROMPT 2 2 "Cognome " -FLAGS "D" -GROUP 2 + PROMPT 2 2 "Cognome " + FLAGS "D" + GROUP 2 END STRING DLG_NULL 20 BEGIN -PROMPT 2 3 "Nome " -FLAGS "D" -GROUP 3 + PROMPT 2 3 "Nome " + FLAGS "D" + GROUP 3 END BOOLEAN CHK_AF4_RESZTERR BEGIN -PROMPT 2 5 "Residenza in zone terremotate" -FIELD LF_ANAG->RESZTERR -HELP "Residenza della persona fisica in zona dichiarate terremotate" + PROMPT 2 5 "Residenza in zone terremotate" + FIELD LF_ANAG->RESZTERR + HELP "Residenza della persona fisica in zona dichiarate terremotate" END NUMBER LST_AF4_EVECC 1 BEGIN -PROMPT 36 5 "Eventi di natura eccezionale " -HELP "Codice degli eventi di natura eccezionale" -FIELD LF_ANAG->EVECC -SHEET "Codice|Descrizione@50" -INPUT LST_AF4_EVECC -OUTPUT LST_AF4_EVECC -ITEM " |Nessuno" -ITEM "1|Richieste di natura estorsiva" -ITEM "2|Zone colpite da eventi alluvionali" -ITEM "3|Alluvionati Giugno 1996" + PROMPT 36 5 "Eventi di natura eccezionale " + HELP "Codice degli eventi di natura eccezionale" + FIELD LF_ANAG->EVECC + SHEET "Codice|Descrizione@50" + INPUT LST_AF4_EVECC + OUTPUT LST_AF4_EVECC + ITEM " |Nessuno" + ITEM "1|Vittime di richieste di natura estorsiva" + ITEM "3|Residenti a Lampedusa e Linosa nel 2011" + ITEM "8|Altri eventi eccezionali" END BOOLEAN FLD_AF4_RFDIVERSA BEGIN -PROMPT 2 7 "Domicilio fiscale diverso da sede legale " -FIELD LF_ANAG->RFDIVERSA -HELP "Dire se il domicilio fiscale e' diverso della sede legale" + PROMPT 2 7 "Domicilio fiscale diverso da sede legale " + FIELD LF_ANAG->RFDIVERSA + HELP "Indicare se il domicilio fiscale è diverso della sede legale" END STRING F_CODREG96 2 @@ -951,6 +951,26 @@ BEGIN FIELD CAUSQUA END +STRING F_CATPAR 2 +BEGIN + PROMPT 41 11 "Categorie particolari " + FIELD CATPAR + HELP "Puo' assumere i valori da 'A' a 'Z3'" +END + +NUMBER F_ESCPRECOMP 1 +BEGIN + PROMPT 41 12 "Esclusione da precompilata " + SHEET "Codice|Descrizione@50" + INPUT F_ESCPRECOMP + OUTPUT F_ESCPRECOMP + ITEM " | " + ITEM "2|2" + HELP "Puo' assumere i valori 1 o 2" + FIELD ESCPRECOMP +END + + GROUPBOX DLG_NULL 78 5 BEGIN PROMPT 0 13 "Codici statistici" diff --git a/ba/ba4200c.uml b/ba/ba4200c.uml index 353910dc1..d4b09eeb7 100755 --- a/ba/ba4200c.uml +++ b/ba/ba4200c.uml @@ -614,7 +614,7 @@ END GROUPBOX DLG_NULL 78 13 BEGIN - PROMPT 0 4 "Dati Societa'" + PROMPT 0 4 "Dati società" END STRING F_COMCOST 4 @@ -629,7 +629,7 @@ BEGIN #include OUTPUT F_COMCOST COM OUTPUT F_DENCOMCOST DENCOM - HELP "Codice del comune dove e' stata costituita la societa'" + HELP "Codice del comune dove e' stata costituita la società" CHECKTYPE NORMAL WARNING "Comune assente" ADD RUN ba4 -0 @@ -638,7 +638,7 @@ END STRING F_DENCOMCOST 50 46 BEGIN PROMPT 26 5 "" - HELP "Nome del comune dove e' stata costituita la societa'" + HELP "Nome del comune dove e' stata costituita la società" COPY USE FLD_AG1_COMRF_COMUNI_DENCOM INPUT DENCOM F_DENCOMCOST #include @@ -651,14 +651,14 @@ DATE FLD_AG3_DATACOST BEGIN PROMPT 2 6 "Data costituz. " FIELD LF_ANAGGIU->DATACOST - HELP "Data di costituzione della societa'" + HELP "Data di costituzione della società" END DATE FLD_AG3_DATAOMOL BEGIN PROMPT 31 6 "Data omologa " FIELD LF_ANAGGIU->DATAOMOL - HELP "Data di omologazione della societa'" + HELP "Data di omologazione della società" WARNING "Data non corretta" VALIDATE DATE_CMP_FUNC >= FLD_AG3_DATACOST END @@ -667,7 +667,7 @@ DATE FLD_AG3_DATAISCRIZ BEGIN PROMPT 2 7 "Data iscrizione " FIELD LF_ANAGGIU->DATAISCRIZ - HELP "Data di iscrizione della societa'" + HELP "Data di iscrizione della società" WARNING "Data non corretta" VALIDATE DATE_CMP_FUNC >= FLD_AG3_DATACOST END @@ -683,7 +683,7 @@ DATE FLD_AG3_DATASCAD BEGIN PROMPT 2 8 "Data scadenza " FIELD LF_ANAGGIU->DATASCAD - HELP "Data di termine attivita' della societa'" + HELP "Data di termine attivita' della società" WARNING "La data di scadenza non puo' precedere quella di costituzione" VALIDATE DATE_CMP_FUNC >= FLD_AG3_DATACOST END @@ -725,12 +725,12 @@ END NUMBER LST_AG3_STATOSOC 1 BEGIN - PROMPT 2 15 "Stato Societa' " + PROMPT 2 15 "Stato società " FIELD LF_ANAGGIU->STATOSOC SHEET "Codice|Stato@50" INPUT LST_AG3_STATOSOC OUTPUT LST_AG3_STATOSOC - HELP "Stato in cui si trova la societa'" + HELP "Stato in cui si trova la società" ITEM " |Sconosciuto" ITEM "1|Soggetto in normale attivita'" ITEM "2|Soggetto in liquidazione per cessazione di attivita'" @@ -740,12 +740,12 @@ END NUMBER LST_AG3_SITSOC 1 BEGIN - PROMPT 29 15 "Situazione societa'" + PROMPT 29 15 "Situazione società" FIELD LF_ANAGGIU->SITSOC SHEET "Codice|Situazione@90" INPUT LST_AG3_SITSOC OUTPUT LST_AG3_SITSOC - HELP "Situazione in cui si trova la societa'" + HELP "Situazione in cui si trova la società" ITEM " |Sconosciuta" ITEM "1|Periodo d'imposta in cui ha avuto inizio la liquidazione" ITEM "2|Periodi d'imposta successivi a quello in cui ha avuto inizio la liquidazione" @@ -761,16 +761,16 @@ NUMBER LST_AG3_NATGIU 2 BEGIN PROMPT 53 15 "Natura Giuridica " FIELD LF_ANAGGIU->NATGIU - HELP "Natura giuridica della societa'" + HELP "Natura giuridica della società" SHEET "Codice|Natura Giuridica@150" INPUT LST_AG3_NATGIU OUTPUT LST_AG3_NATGIU ITEM " |Sconosciuta" - ITEM "1|Societa' in accomandita per azioni" - ITEM "2|Societa' a resposabilita' limitata" - ITEM "3|Societa' per azioni" - ITEM "4|Societa' cooperative e loro consorzi iscritti nei registri prefettizi e nello schedario generale delle cooperazioni" - ITEM "5|Altre societa' cooperative" + ITEM "1|società in accomandita per azioni" + ITEM "2|società a resposabilita' limitata" + ITEM "3|società per azioni" + ITEM "4|società cooperative e loro consorzi iscritti nei registri prefettizi e nello schedario generale delle cooperazioni" + ITEM "5|Altre società cooperative" ITEM "6|Mutue assicuratrici" ITEM "7|Consorzi con personalita' giuridica" ITEM "8|Associazioni riconosciute" @@ -782,32 +782,32 @@ BEGIN ITEM "14|Enti pubblici economici" ITEM "15|Enti pubblici non economici" ITEM "16|Casse mutue e fondi di previdenza, assistenza, pensioni o simili con o senza personalita' giuridica" - ITEM "17|Opere pie e societa' di mutuo soccorso" + ITEM "17|Opere pie e società di mutuo soccorso" ITEM "18|Enti ospedalieri" ITEM "19|Enti ed istituti di previdenza e asssistenza sociale" ITEM "20|Aziende autonome di cure, soggiorno e turismo" ITEM "21|Aziende regionali, provinciali, comunali e loro consorzi" - ITEM "22|Societa', organizzazioni ed enti costituiti all'estero e non altrimenti classificabili con sede dell'amministrazione ad oggetto principale in Italia" - ITEM "23|Societa' semplici, irregolari o di fatto" - ITEM "24|Societa' in nome collettivo" - ITEM "25|Societa' in accomamdita semplice" - ITEM "26|Societa' d'armamento" + ITEM "22|società, organizzazioni ed enti costituiti all'estero e non altrimenti classificabili con sede dell'amministrazione ad oggetto principale in Italia" + ITEM "23|società semplici, irregolari o di fatto" + ITEM "24|società in nome collettivo" + ITEM "25|società in accomamdita semplice" + ITEM "26|società d'armamento" ITEM "27|Associazioni tra artisti e professionisti" ITEM "28|Aziende coniugali" ITEM "29|GEIE" - ITEM "30|Societa'semplici irregolari e di fatto (Non residenti)" - ITEM "31|Societa' in nome collettivo (Non residenti)" - ITEM "32|Societa' in accomandita semplice (Non residenti)" - ITEM "33|Societa' di armamento (Non residenti)" + ITEM "30|societàsemplici irregolari e di fatto (Non residenti)" + ITEM "31|società in nome collettivo (Non residenti)" + ITEM "32|società in accomandita semplice (Non residenti)" + ITEM "33|società di armamento (Non residenti)" ITEM "34|Associazioni tra professionisti (Non residenti)" - ITEM "35|Societa' in accomandita per azioni (Non residenti)" - ITEM "36|Societa' a responsabilita' limitata (Non residenti)" - ITEM "37|Societa' per azioni (Non residenti)" + ITEM "35|società in accomandita per azioni (Non residenti)" + ITEM "36|società a responsabilita' limitata (Non residenti)" + ITEM "37|società per azioni (Non residenti)" ITEM "38|Consorzi (Non residenti)" ITEM "39|Altri enti ed istituti (Non residenti)" ITEM "40|Associazioni riconosciute, non riconsciute e di fatto (Non residenti)" ITEM "41|Fondazioni (Non residenti)" - ITEM "42|Opere pie e societa'di mutuo soccorso (Non residenti)" + ITEM "42|Opere pie e societàdi mutuo soccorso (Non residenti)" ITEM "43|Altre organizzazioni di persone e di beni (Non residenti)" END @@ -864,7 +864,7 @@ BEGIN PROMPT 42 5 "Numero azioni " FIELD LF_ANAGGIU->NAZIONI FLAGS "R" - HELP "Numero di azioni emesse dalla societa'" + HELP "Numero di azioni emesse dalla società" END NUMBER FLD_AG4_VALNOM 15 @@ -1002,14 +1002,14 @@ NUMBER LST_AG5_EVECC 1 BEGIN PROMPT 37 4 "Eventi di natura eccezionale " FIELD LF_ANAG->EVECC - HELP "Codice degli eventi naturali eccezionali accaduti alla ditta" + HELP "Codice degli eventi eccezionali" SHEET "Codice|Descrizione@50" INPUT LST_AG5_EVECC OUTPUT LST_AG5_EVECC ITEM " |Nessuno" - ITEM "1|Richieste di natura estorsiva" - ITEM "2|Zone colpite da eventi alluvionali" - ITEM "3|Alluvionati Giugno 1996" + ITEM "1|Vittime di richieste di natura estorsiva" + ITEM "3|Residenti a Lampedusa e Linosa nel 2011" + ITEM "8|Altri eventi eccezionali" END BOOLEAN CHK_AG5_RFDSL @@ -1039,14 +1039,33 @@ BEGIN FIELD CAUSQUA END +STRING F_CATPAR 2 +BEGIN + PROMPT 41 6 "Categorie particolari " + FIELD CATPAR + HELP "Puo' assumere i valori da 'A' a 'Z3'" +END + +NUMBER F_ESCPRECOMP 1 +BEGIN + PROMPT 41 7 "Esclusione da precompilata " + SHEET "Codice|Descrizione@50" + INPUT F_ESCPRECOMP + OUTPUT F_ESCPRECOMP + ITEM " | " + ITEM "1|1" + HELP "Puo' assumere i valori 1 o 2" + FIELD ESCPRECOMP +END + GROUPBOX DLG_NULL 78 5 BEGIN - PROMPT 0 7 "Codici statistici" + PROMPT 0 8 "Codici statistici" END STRING FLD_AG6_CODSTAT1 7 BEGIN - PROMPT 2 8 "1 " + PROMPT 2 9 "1 " FIELD LF_ANAG->CODSTAT1 USE %STT INPUT CODTAB FLD_AG6_CODSTAT1 @@ -1061,13 +1080,13 @@ END STRING FLD_AG6_CODSTAT1_TABSTT_S0 57 BEGIN - PROMPT 16 8 "" + PROMPT 16 9 "" FLAGS "D" END STRING FLD_AG6_CODSTAT2 7 BEGIN - PROMPT 2 9 "2 " + PROMPT 2 10 "2 " FIELD LF_ANAG->CODSTAT2 COPY USE FLD_AG6_CODSTAT1 INPUT CODTAB FLD_AG6_CODSTAT2 @@ -1081,13 +1100,13 @@ END STRING FLD_AG6_CODSTAT2_TABSTT_S0 57 BEGIN - PROMPT 16 9 "" + PROMPT 16 10 "" FLAGS "D" END STRING FLD_AG6_CODSTAT3 7 BEGIN - PROMPT 2 10 "3 " + PROMPT 2 11 "3 " FIELD LF_ANAG->CODSTAT3 COPY USE FLD_AG6_CODSTAT1 INPUT CODTAB FLD_AG6_CODSTAT3 @@ -1101,48 +1120,48 @@ END STRING FLD_AG6_CODSTAT3_TABSTT_S0 57 BEGIN - PROMPT 16 10 "" + PROMPT 16 11 "" FLAGS "D" END TEXT DLG_NULL BEGIN - PROMPT 2 12 "Note" + PROMPT 2 13 "Note" END STRING FLD_AG6_NOTE1 70 BEGIN - PROMPT 3 13 "" + PROMPT 3 14 "" FIELD LF_ANAGGIU->NOTE1 - HELP "Eventuali note relative alla societa'" + HELP "Eventuali note relative alla società" END STRING FLD_AG6_NOTE2 70 BEGIN - PROMPT 3 14 "" + PROMPT 3 15 "" FIELD LF_ANAGGIU->NOTE2 - HELP "Eventuali note relative alla societa'" + HELP "Eventuali note relative alla società" END STRING FLD_AG6_NOTE3 70 BEGIN - PROMPT 3 15 "" + PROMPT 3 16 "" FIELD LF_ANAGGIU->NOTE3 - HELP "Eventuali note relative alla societa'" + HELP "Eventuali note relative alla società" END STRING FLD_AG6_NOTE4 70 BEGIN - PROMPT 3 16 "" + PROMPT 3 17 "" FIELD LF_ANAGGIU->NOTE4 - HELP "Eventuali note relative alla societa'" + HELP "Eventuali note relative alla società" END STRING FLD_AG6_NOTE5 70 BEGIN - PROMPT 3 17 "" + PROMPT 3 18 "" FIELD LF_ANAGGIU->NOTE5 - HELP "Eventuali note relative alla societa'" + HELP "Eventuali note relative alla società" END ENDPAGE diff --git a/ba/ba7100.cpp b/ba/ba7100.cpp index c42e78996..898e3f893 100755 --- a/ba/ba7100.cpp +++ b/ba/ba7100.cpp @@ -1,1758 +1,1812 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ba7.h" -#include "ba7100a.h" -#define NOT_TRANS -883 -#define NOT_GEST -884 - -/////////////////////////////////////////////////////////// -// TConfig utilities -/////////////////////////////////////////////////////////// - -/* Obsolete -static const TString& set_ini_var(int cfg, const char* para, const char* var, const char* val) -{ - TConfig ini(cfg, para); - const TString& prev = ini.get(var); - if (val != NULL) - ini.set(var, val); - if (prev.blank()) - return EMPTY_STRING; - TString& tmp = get_tmp_string(); - tmp = prev; - return tmp; -} - -inline const TString& get_ini_var(int cfg, const char* para, const char* var) -{ return ini_get_string(cfg, para, var); } -*/ - -/////////////////////////////////////////////////////////// -// TMail_box -/////////////////////////////////////////////////////////// - -class TMail_box : public TSocketClient -{ - unsigned long _connection; - -public: - bool default_params(TString& server, TString& user,TString& password); - - bool logon(const char* server = NULL, - const char* usr = NULL, const char* pwd = NULL); - virtual bool ok() const { return _connection != NULL; } - - bool list(TString_array& a); - int get(TMail_messages& m); - bool remove(const char* id); - - void logoff(); - - TMail_box(); - ~TMail_box(); -}; - -bool TMail_box::default_params(TString& server, TString& user,TString& password) -{ - bool ok = true; - if (server.blank()) - { - server = ini_get_string(CONFIG_INSTALL, "Server", "POP3"); - if (server.empty()) - ok = false; - } - if (user.blank()) - user = ::user(); - if (password.blank()) - { - const TString& pwd = cache().get(LF_USER, user).get("PASSWORD"); - password = ::decode(pwd); - } - return ok; -} - -bool TMail_box::logon(const char* ser, const char* usr, const char* pwd) -{ - if (_connection) - logoff(); - - if (!IsOk()) - return error_box(TR("Impossibile inizializzare il client POP3")); - - TString server(ser); - TString user(usr); - TString password(pwd); - if (!default_params(server, user, password)) - return error_box(TR("E' necessario specificare un server POP3, un utente ed una password")); - - TString msg; - msg << TR("Connessione al server POP3 ") << server; - xvtil_statbar_set(msg); - - _connection = QueryConnection("110", server); - if (_connection != 0) - { - msg.cut(0) << TR("Connesso al server POP3 ") << server; - xvtil_statbar_set(msg); - - TString buf(255); - ReadLine(_connection, buf); - if (buf[0] != '+') - return error_box(FR("Il server POP3 %s non risponde. Risultato:\n'%s'"), - (const char*)server, (const char *)buf); - - buf = "USER "; buf << user << "\r\n"; - WriteLine(_connection, buf); - TString req = buf; - ReadLine(_connection, buf); - if (buf[0] != '+') - return error_box(FR("Il server POP3 %s non accetta l'utente %s\nRichiesta : %sRisultato : %s"), - (const char*)server, (const char*)user, (const char *) req, (const char *)buf); - - buf = "PASS "; buf << password << "\r\n"; - WriteLine(_connection, buf); - req = buf; - ReadLine(_connection, buf); - if (buf[0] != '+') - return error_box(FR("Il server POP3 %s non accetta la password dell'utente %s\nRichiesta : %sRisultato : %s"), - (const char*)server, (const char*)user, (const char *) req, (const char *)buf); - } - else - return error_box(FR("Impossibile contattare il server POP3 %s"), - (const char*)server); - - return true; -} - -void TMail_box::logoff() -{ - if (_connection) - { - WriteLine(_connection, "QUIT\r\n"); - RemoveConnection(_connection); - _connection = NULL; - } -} - -bool TMail_box::list(TString_array& a) -{ - bool ok = _connection != NULL; - if (ok) - { - TString buf; - buf = "LIST\r\n"; - WriteLine(_connection, buf); - ReadLine(_connection, buf); - ok = buf[0] == '+'; - while (ok) - { - if (!ReadLine(_connection, buf)) - break; // Unexpected EOF - if (buf[0] == '.') - break; - int pos = buf.find(' '); - if (pos > 0) - buf.cut(pos); - a.add(buf); - } - } - return ok; -} - -HIDDEN int str2month(const char* str) -{ - const char* const mese[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - int m; - for (m = 11; m > 0; m--) - { - if (xvt_str_compare_ignoring_case(str, mese[m]) == 0) - break; - } - return m+1; -} - -enum EncodingType { enc_plain_text, enc_quoted_printable, enc_base64 }; - -int TMail_box::get(TMail_messages& m) -{ - // Lista dei caratteri validi - const char* const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+*"; - - // Lista per decodifica dei caratteri validi - char Deco64[256]; - memset(Deco64, ' ', sizeof(Deco64)); - - for (int i = 0; Base64[i]; i++) - Deco64[Base64[i]] = i; - TString_array a; - list(a); - - TString buf, boundary, msg_line; - - m.destroy(); - FOR_EACH_ARRAY_ROW(a, r, row) - { - TMail_message* msgptr = new TMail_message(user()); - m.add(msgptr); - TMail_message& msg = *msgptr; - - buf = "RETR "; buf << *row << "\r\n"; - WriteLine(_connection, buf); - ReadLine(_connection, buf); - bool ok = buf[0] == '+'; - EncodingType encoding = enc_plain_text; - bool in_body = false; - bool in_section = false; - bool buf_already_read = false; - boundary.cut(0); - - while (ok) - { - if (!buf_already_read) - { - if (!ReadLine(_connection, buf)) - { - ok = false; - break; // Unexpected EOF - } - } - else - buf_already_read = false; - if (buf[0] == '.') - { - buf.ltrim(1); - if (buf.blank()) - break; - } - if (in_body) - { - if (buf[0] == '-' && boundary.not_empty() && buf.find(boundary) >= 0) - break; // Ignora sezioni di attachment - - switch (encoding) - { - case enc_base64: - { - unsigned val = 0; - int bits = 0; - msg_line.cut(0); - for (const char* s = buf; *s && *s != '='; s++) - { - if (*s==0x0A || *s==0x0D || *s==0x20 || *s==0x09) - continue; // Salta eventuali blanks - val <<= 6; - val |= Deco64[*s]; - bits += 6; - if (bits >= 8) - { - const char c = char((val >> (bits - 8)) & 0xFF); - msg_line << c; - bits -= 8; - } - } - msg.add_line(msg_line); - } - break; - case enc_quoted_printable: - { - msg_line.cut(0); - for (const char* s = buf; *s; s++) - { - if (*s == '=') - { - s++; - if (*s >= ' ') - { - int c; sscanf(s, "%2X", &c); - msg_line << char(c); - s++; - } - } - else - msg_line << *s; - } - msg.add_line(msg_line); - } - break; - default: - buf.rtrim(); - msg.add_line(buf); - break; - } - } - else - { - if (boundary.not_empty()) - { - if (buf.blank()) - { - in_body = in_section; - } - else - { - if (buf.find(boundary) >= 0) - in_section = true; - } - } - else - { - if (buf.blank()) - { - in_body = true; - continue; - } - } - - if (buf.compare("From:", 5, true) == 0) - { - buf.ltrim(6); buf.trim(); - msg.set_sender(buf); - continue; - } - if (buf.compare("To:", 3, true) == 0) - { - buf.ltrim(4); buf.trim(); - msg.add_recipient(buf); - continue; - } - if (buf.compare("Cc:", 3, true) == 0) - { - buf.ltrim(4); buf.trim(); - msg.add_copy_recipient(buf); - continue; - } - if (buf.compare("Subject:", 8, true) == 0) - { - buf.ltrim(9); buf.trim(); - msg.set_subject(buf); - continue; - } - if (buf.compare("Date:", 5, true) == 0) - { - TToken_string d(buf.mid(6), ' '); d.trim(); - int giorno = d.get_int(1); - int mese = str2month(d.get()); - int anno = d.get_int(); - if (anno < 100) anno += 2000; - TString16 ora = d.get(); - buf.cut(0); - buf << anno << '/' << mese << '/' << giorno << ' ' << ora; - msg.set_date_time(buf); - continue; - } - if (buf.compare("Content-Transfer-Encoding:", 26, true) == 0) - { - if (buf.find("base64") > 0) - encoding = enc_base64; else - if (buf.find("quoted-printable") > 0) - encoding = enc_quoted_printable; - continue; - } - if (buf.compare("Content-Type:", 13, true) == 0) - { - int bnd = buf.find("oundary="); // Funziona per Boundary e boundary - if (bnd < 0) - { - ReadLine(_connection, buf); - bnd = buf.find("oundary="); - if (bnd < 0) - buf_already_read = true; - } - if (bnd > 0) - { - const int apicia = buf.find('"', bnd); - const int apicic = buf.find('"', apicia+1); - if (apicia > 0 && apicic > apicia) - boundary = buf.sub(apicia+1, apicic); - } - continue; - } - } - } - } - return m.items(); -} - -bool TMail_box::remove(const char* id) -{ - bool ok = _connection != NULL; - if (ok) - { - TString buf; - buf << "DELE " << id << "\r\n"; - WriteLine(_connection, buf); - ReadLine(_connection, buf); - ok = buf[0] == '+'; - } - return ok; -} - -TMail_box::TMail_box() : _connection(NULL) -{ -} - -TMail_box::~TMail_box() -{ - logoff(); -} - -/////////////////////////////////////////////////////////// -// TFilter_expr -/////////////////////////////////////////////////////////// - -class TFilter_expr : public TExpression -{ - TAutomask& _mask; - -protected: - virtual bool print_error(const char* msg) const; - -public: - TFilter_expr(TAutomask& m, int logicnum, const char* expr); - virtual ~TFilter_expr() { } -}; - -bool TFilter_expr::print_error(const char* msg) const -{ - return _mask.error_box(msg); -} - -TFilter_expr::TFilter_expr(TAutomask& m, int logicnum, const char* expr) - : _mask(m) -{ - bool ok = set(expr, _strexpr); - if (ok) - { - if (logicnum < LF_USER || logicnum >= prefix().items()) - logicnum = LF_TABCOM; // Niente errori fatali, se possibile - - const TRectype rec(logicnum); - - for (int i = 0; i < numvar(); i++) - { - const TFixed_string name(varname(i)); - int num = logicnum; - bool ok = rec.exist(name); - - if (!ok) - { - const TFieldref f(name, 0); - int num = table2logic(f.id()); - const TRectype join(num); - ok = join.exist(f.name()); - } - if (!ok) - { - _error = 883; - TString msg; - msg.format(FR("Il campo %s non appartiene al file %d"), varname(i), logicnum); - print_error(msg); - break; - } - } - } -} - - -/////////////////////////////////////////////////////////// -// TMailer_mask -/////////////////////////////////////////////////////////// - -class TMailer_mask : public TAutomask -{ - long _timer_id; - long _secs; - long _interval; - int _mail_semaphore; - TMail_messages _box; - bool _sequential; - clock_t _last_use; - - TString_array _key1; // Elenco dei campi della chiave principale dei files - TAssoc_array _apps; // Elenco delle applicazioni per processare i files - -protected: - virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); - virtual long handler(WINDOW win, EVENT* ep); - void log(const char* text); - -protected: - bool file2app(const TString& file, TString& app) const; - void expand_tabs(TMail_message& str, const int tab = 8) const; - - void save_sheet(TConfig& ini, short dlg, const char* var) const; - void load_sheet(TConfig& ini, short dlg, const char* var); - - TToken_string& get_key1(int lf) const; - bool build_key1(int lf, const TString& body, TToken_string& key, TString& action) const; - bool build_key1(const TMail_message& msg, TToken_string& key, TString& action) const; - void find_redundant_messages(); - - void track(const TMail_message& msg, const TString& app, const TString& action, int err); - int exec_app(const TString& appname, TMail_message & msg, TToken_string & sh_row); - void scan_ini_files(const char* dir, TString_array& result, int level) const; - void scan_dir(const TFilename& dir, TMail_messages& box) const; - bool unattended() const; - -public: - void test_delete(); - void fill_messages(); - int save_sheet_line(int line = -1); - void save_all_lines(); - void exec_scripts(); - void auto_save_all(bool manual); - - void save() const; - void load(); - - TMailer_mask(); - virtual ~TMailer_mask(); -}; - -void TMailer_mask::test_delete() -{ - if (_mail_semaphore != 0) - return; - _mail_semaphore = 1; - TWait_cursor hourglass; - - xvtil_statbar_set(TR("Eliminazione messaggi...")); - do_events(); - - TSheet_field& sf = sfield(F_MESSAGES); - const int sender_pos = sf.cid2index(F_SENDER); - const int mailer_pos = sf.cid2index(F_MAILER); - const int msgid_pos = sf.cid2index(F_ID); - TString4 mailer; - TString id; - - TMail_messages mapidel; // Lista dei messaggi MAPI da cancellare - - TMail_box mailbox; - FOR_EACH_SHEET_ROW_BACK(sf, nrow, row) if (*row->get(0) == 'X') - { - row->get(mailer_pos, mailer); - row->get(msgid_pos, id); - bool deleted = false; - if (mailer == "POP3") - { - if (!mailbox.ok()) - { - if (!mailbox.logon(get(F_SERVER), get(F_USER), get(F_PASSWORD))) - break; - } - deleted = mailbox.remove(id); - } else - if (mailer == "CNP") - { - TFilename file; - row->get(sender_pos, file); // Cartella di provenienza - file.add(id); - file.ext("ini"); - deleted = file.fremove(); - } else - if (mailer == "MAPI") - { - TMail_message* msg = new TMail_message(""); - msg->set_id(id); - mapidel.add(msg); - deleted = true; - } - if (deleted) - { - _box.destroy(nrow, true); - sf.destroy(nrow, false); - } - else - { - TString err = TR("Impossibile cancellare il messaggio"); - err << ' ' << id; - xvtil_statbar_set(err); - do_events(); - beep(2); // Error sound - } - } - if (mailbox.ok()) - mailbox.logoff(); - - if (mapidel.items() > 0) - { - xvtil_statbar_set(TR("Eliminazione messaggi MAPI...")); - do_events(); - mapidel.remove(); - } - - sf.force_update(); - - xvtil_statbar_set(TR("Pronto")); - do_events(); - _mail_semaphore = 0; -} - -void TMailer_mask::expand_tabs(TMail_message& msg, const int tab) const -{ - const int items = msg.items(); - for (int n = 0; n < items; n++) - { - TString & str = msg.row(n); - int start = 0; - - for (int i = 0; str[i]; i++) - { - switch(str[i]) - { - case '\n': - case '\r': - start = i+1; - break; - case '\t': - { - const int t = tab - ((i-start) % tab) - 1; - str[i] = ' '; - if (t > 0) - { - TString80 spac; spac.spaces(t); - str.insert(spac, i+1); - i += t; - } - } - break; - default: - break; - } - } - } -} - -void TMailer_mask::scan_ini_files(const char* dir, TString_array& result, int level) const -{ - TFilename mask = dir; mask.add("*.ini"); - - SLIST files = xvt_fsys_list_files("ini", mask, FALSE); - for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e)) - { - const char* fn = xvt_slist_get(files, e, NULL); - result.add(fn); - } - xvt_slist_destroy(files); - - if (level == 0) - { - mask = dir; mask.add("*"); - files = xvt_fsys_list_files(DIR_TYPE, mask, TRUE); - const int tot = xvt_slist_count(files); - if (tot > 0) - { - TProgind pi(tot, TR("Elaborazione cartelle transazioni"), true, true); - for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e)) - { - if (!pi.addstatus(1)) - break; - const char* fn = xvt_slist_get(files, e, NULL); - if (dexist(fn)) - scan_ini_files(fn, result, level+1); - } - } - xvt_slist_destroy(files); - } -} - -void TMailer_mask::scan_dir(const TFilename& dir, TMail_messages& box) const -{ - box.destroy(); - TString_array msg; - scan_ini_files(dir, msg, 0); - - TString subject, text, strdata; - TToken_string id(_MAX_FNAME, '_'); - FOR_EACH_ARRAY_ROW(msg, r, row) - { - const int size = fsize(*row); - if (size > 64 && size < 48*1024) - { - char* buffer = text.get_buffer(size); - TScanner scanner(*row); - - memset(buffer, 0 , size); - scanner.read(buffer, size); - buffer[size] = '\0'; - - if (text.starts_with("[TRANSACTION]")) // Zucchetti maiuscolo! - { - const char* maiusc[] = { "[TRANSACTION]", "ACTION=", "FIRM=", "MODE=I", "USER=", "RESULT=", "ERRORMSG=", NULL}; - const char* minusc[] = { "[Transaction]", "Action=", "Firm=", "Mode=A", "User=", "Result=", "Error= ", NULL}; - for (int w = 0; maiusc[w]; w++) - { - const int i = text.find(maiusc[w]); - if (i >= 0) - text.overwrite(minusc[w], i); - } - } - - subject.cut(0); - if (text.find("[Transaction]") >= 0) - { - int parc = text.find(']'); // fine primo paragrafo - if (parc > 0) - { - int para = text.find('[', parc+1); - if (para > 0) - { - parc = text.find(']', para+1); - if (parc > 0) - subject = text.sub(para+1, parc); - } - } - } - if (subject.full()) - { - FILE_SPEC fs; xvt_fsys_convert_str_to_fspec(*row, &fs); - - TMail_message* msg = new TMail_message(user(), subject, text, fs.dir.path); - msg->set_id(id = fs.name); - - if (id.items() == 3) // Nome file in formato YYMMDD_HHMMSS_NN.ini - { - strdata = id.get(0); strdata.insert("20"); - const TDate data(strdata); - const long hhmmss = id.get_long(1); - msg->set_date_time(data, hhmmss); - } - else - { - const time_t dt = xvt_fsys_get_file_attr(&fs, XVT_FILE_ATTR_MTIME); - const struct tm* t = localtime(&dt); - msg->set_date_time(TDate(t->tm_mday, t->tm_mon, t->tm_year+1900), - t->tm_hour*10000 + t->tm_min*100 + t->tm_sec); - } - - box.add(msg); - } - } - } -} - -void TMailer_mask::fill_messages() -{ - if (_mail_semaphore != 0) - return; - _mail_semaphore = 1; - - disable(DLG_DELREC); - - TWait_cursor hourglass; - - TFilename server(get(F_SERVER)); - TString80 user(get(F_USER)); - TString80 password(get(F_PASSWORD)); - TMail_box mailbox; - if (mailbox.default_params(server, user, password)) - { - set(F_SERVER, server); - set(F_USER, user); - set(F_PASSWORD, password); - } - expand_sys_vars(server); - - int totmapi = 0; - - if (get_bool(F_MAPI)) - { - xvtil_statbar_set(TR("Ricezione messaggi MAPI...")); - do_events(); - totmapi = _box.get(); - - for (int i = 0; i < totmapi; i++) - { - TMail_message& msg = _box.msg(i); - const TString& subject = msg.subject(); - bool kill = msg.empty() || subject.blank() || subject.len() > 4; - if (!kill) - { - TString& line = msg.row(0); - int pos = line.find("[Transaction]"); - if (pos) - { - if (pos < 0) - kill = true; - else - line.ltrim(pos); - } - pos = line.find("-----"); - if (pos > 0) - line.cut(pos); - } - if (kill) // Not a Campo transaction - _box.destroy(i); - } - _box.pack(); - totmapi = _box.items(); - } - - TString4 mailer; - if (isalpha(server[0]) && server[1] == ':' && is_slash(server[2]) && server.exist()) - { - mailer = "CNP"; - xvtil_statbar_set(TR("Ricezione messaggi CNP ...")); - do_events(); - scan_dir(server, _box); - } - else - { - mailer = "POP3"; - if (server.full()) - { - xvtil_statbar_set(TR("Ricezione messaggi POP3...")); - do_events(); - mailbox.logon(server, user, password); - mailbox.get(_box); - mailbox.logoff(); - } - } - - TSheet_field& sf = sfield(F_MESSAGES); - sf.destroy(); - TString mess; - FOR_EACH_ARRAY_ITEM(_box, m, obj) - { - TMail_message& msg = _box.msg(m); - TToken_string& row = sf.row(-1); - row.add(msg.sender(), sf.cid2index(F_SENDER)); - row.add(msg.date(), sf.cid2index(F_DATE)); - const real t = msg.time(); - row.add(t.string("@@:@@:@@"), sf.cid2index(F_TIME)); - row.add(msg.subject(), sf.cid2index(F_SUBJECT)); - expand_tabs(msg); - - mess.cut(0); - FOR_EACH_ARRAY_ROW(msg, i, msgrow) - { - mess << *msgrow; - if (mess.len() >= 1024) - { - mess.cut(1024); - break; - } - } - row.add(mess, sf.cid2index(F_BODY)); - if (m < totmapi) - { - row.add("MAPI", sf.cid2index(F_MAILER)); - row.add(msg.id(), sf.cid2index(F_ID)); - } - else - { - row.add(mailer, sf.cid2index(F_MAILER)); - if (mailer == "CNP") - row.add(msg.id(), sf.cid2index(F_ID)); - else - row.add(m-totmapi+1, sf.cid2index(F_ID)); - } - } - sf.force_update(); - - xvtil_statbar_set(TR("Pronto")); - - _mail_semaphore = 0; - return; -} - -bool TMailer_mask::file2app(const TString& file, TString& app) const -{ - bool ok = false; - - const TString* run = (const TString*)_apps.objptr(file); - if (run == NULL) - { - TString16 appname; appname << "Edit_" << file; - app = ini_get_string(CONFIG_DITTA, "ba7", appname); - if (app.empty()) - { - if (isdigit(file[0])) - { - const int filenum = atoi(file); - if (filenum >= LF_USER && filenum < prefix().items()) - { - TLocalisamfile isf(filenum); - ok = isf.get_relapp(app); - } - } - else - { - const int len = file.len(); - if (len == 3 || (len == 4 && file[0] == '%')) - { - TTable table(file); - ok = table.get_relapp(app); - } else - if (len >= 4 && file[0] == '&') - { - TModule_table tabmod(file); - ok = tabmod.get_relapp(app); - } - } - } - else - ok = true; - - ((TMailer_mask*)this)->_apps.add(file, app); // Fool const - } - else - { - app = *run; - ok = app.full(); - } - return ok; -} - -bool is_incomplete(const TString& l) -{ - if (l[0] == '[') - return false; - - const char a = l.right(1)[0]; - if (a == '=') - return true; - - const int eq = l.find("= '"); - if (eq > 0 && eq < 20) - return a != '\''; - - return false; -} - -void adjust_long_lines(const TFilename& tmp) -{ - TFilename dst_name; dst_name.temp(); - ofstream dst(dst_name); - - bool adjusted = false; - - TScanner org(tmp); - while (true) - { - const TString& l = org.line(); - if (l.empty()) - break; - if (is_incomplete(l)) - { - adjusted = true; - dst << l; - org.line(); - char s = l[0]; - if (s == '\'' || s == '"') - { - char c = l.right(1)[0]; - while (c != '\'' && c != '"') - { - dst << l; - org.line(); - c = l.right(1)[0]; - } - } - else - dst << '\n'; - } - dst << l << '\n'; - } - org.close(); - dst.close(); - if (adjusted) - fcopy(dst_name, tmp); - dst_name.fremove(); -} - -void TMailer_mask::track(const TMail_message& msg, const TString& app, const TString& action, int err) -{ - const TString& fname = get(F_TRACKING); - - if (fname.full()) - { - const char fldsep = '\t'; - const char recsep = '\n'; - - ofstream log(fname, ios::app); - - log << msg.sender() << fldsep; - - log << msg.date() << fldsep; - const real t = msg.time(); - log << t.string("@@:@@:@@") << fldsep; - - TToken_string k1; - TString act; - build_key1(msg, k1, act); - log << k1.get(0) << fldsep; - - const int pipe = k1.find(k1.separator()); - k1.ltrim(pipe+1); - log << k1 << fldsep; - - log << app << fldsep << action << fldsep << err << fldsep; - - log << recsep; - } -} - -int TMailer_mask::exec_app(const TString& appname, TMail_message& msg, TToken_string & sh_row) -{ - int err = NOERR; - TString action; - if (appname.compare("sink", -1, true) == 0) - { - FOR_EACH_ARRAY_ROW(msg, r, row) - { - int s = row->find("\nAction"); - if (s > 0) - { - s = row->find('=', s); - const int e = row->find('\n', s); - action = row->sub(s+1, e); - action.trim(); - break; - } - } - } - else - { - TFilename tmp; tmp.temp("trn", "ini"); - if (tmp.full()) - { - ofstream outf(tmp); - const int items = msg.items(); - TString message; - for (int i = 0; i < items; i++) - { - message = msg.row(i); - message.replace('\r', '\n'); - outf << message; - } - outf.close(); - adjust_long_lines(tmp); - - TConfig ini(tmp, "Transaction"); - ini.set("From", msg.sender()); - action = ini.get("Action"); - } - - TString command_line(appname); - command_line << " /i" << tmp; - TExternal_app app(command_line); - err = app.run(false, true, false); // Don't iconize (nor restore) the task window! - xvt_sys_sleep(1000); - - if (err == NOERR) - { - TConfig ini(tmp, "Transaction"); - if (ini.get("Result").compare("OK", -1, true) == 0 || - ini.get("Action").compare("RUN", -1, true) == 0) - err = 0; - else - if (get_bool(F_DELCANCEL) && ini.get("Result").compare("Cancel", -1, true) == 0) - err = 0; - else - err = ini.get_int("Error"); - - TFilename backup = get(F_BACKUP); - expand_sys_vars(backup); - if (backup.exist()) - { - const TSheet_field& sf = sfield(F_MESSAGES); - - TString id; - TFilename file; - sh_row.get(sf.cid2index(F_ID), id); - sh_row.get(sf.cid2index(F_SENDER), file); // Cartella di provenienza - file.add(id); - file.ext("ini"); - - TFilename dest = backup; - dest.add(file.name()); - fcopy(tmp, dest); - } - } - tmp.fremove(); - } - - track(msg, appname, action, err); - - return err; -} - -int TMailer_mask::save_sheet_line(int nrow) -{ - int err = NOERR; - TSheet_field& sf = sfield(F_MESSAGES); - TMask& m = sf.sheet_mask(); - - if (nrow < 0) - nrow = sf.selected(); - else - sf.update_mask(nrow); - - TToken_string& row = sf.row(nrow); - - const TString& msg = m.get(F_BODY); - if (msg.find("[Transaction]") < 0) - { - err = NOT_TRANS; - return false; // It's not a transaction - } - - TString subj = m.get(F_SUBJECT); - TIsam_handle logic = LF_TAB; - if (isalpha(subj[0])) // Controlla se la tabella in realtà è comune ed aggiunge il simbolino % - { - TString8 para; para << '[' << LF_TABCOM << ']'; - if (msg.find(para) > 0) - subj.insert("%"); - } - else - { - logic = atoi(subj); - if (logic == LF_TAB || logic == LF_TABCOM) - { - TString8 para; para << '[' << logic << ']'; - int pos = msg.find(para); - if (pos > 0) - { - pos = msg.find("\nCOD", pos+3); - if (pos > 0) - { - TToken_string line(msg.mid(pos, 10), '='); - line.strip_spaces(); - if (line.items() == 2) - { - subj = line.get(1); subj.cut(3); - if (logic == LF_TABCOM) - subj.insert("%"); - } - } - } - } - } - - TFilename appname; - if (!file2app(subj, appname)) // It hasn't a valid application - return err = NOT_GEST; - - TMail_message& full_msg = _box.msg(nrow); - err = exec_app(appname, full_msg, row); - if (err == _iskeynotfound) - { - TString & first_row = full_msg.row(0); - int pos = first_row.find("MODIFY"); - if (pos > 0) - { - first_row.overwrite("INSERT", pos); - err = exec_app(appname, full_msg, row); - } - } - - if (err == NOERR) - { - if (m.is_running()) - { - m.set(F_CHECKED, "X"); - m.stop_run(K_AUTO_ENTER); - } - else - { - row.add("X", 0); - sf.force_update(nrow); - } - } - - return err; -} - -TToken_string& TMailer_mask::get_key1(int lf) const -{ - TString_array& k = (TString_array&)_key1; // Fool constness - TToken_string* key = k.rowptr(lf); - if (key == NULL) - { - key = new TToken_string; // Creo una nuova entry - const RecDes& recd = prefix().get_recdes(lf); // Descrizione del record della testata - const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1 - for (int i = 0; i < kd.NkFields; i++) - { - const int nf = kd.FieldSeq[i] % MaxFields; - const RecFieldDes& rf = recd.Fd[nf]; - key->add(rf.Name); - } - k.add(key, lf); - } - return *key; -} - -bool TMailer_mask::build_key1(int lf, const TString& body, TToken_string& key, TString& action) const -{ - key.format("%d", lf); - - TString16 field; // Nome del campo chiave - TString value; // Valore del campo chiave - - TToken_string& key1 = get_key1(lf); // Elenco dei campi chiave - FOR_EACH_TOKEN(key1, fld) - { - field = fld; field.insert("\n"); - const int start = body.find(field); - if (start < 0) - return false; - const int equal = body.find('=', start); - if (equal < 0) - return false; - const int stop = body.find('\n', equal); - if (stop < 0) - return false; - value = body.sub(equal+1, stop); - value.trim(); - if (value[0] == '"' && value.right(1) == "\"") // Toglie eventuali virgolette - { - value.rtrim(1); - value.ltrim(1); - } - key.add(value); - } - - const int act = body.find("\nAction"); - const int ugu = act > 0 ? body.find('=', act) : -1; - const int nwl = ugu > 0 ? body.find('\n', ugu) : -1; - if (act > 0 && ugu > act && ugu < nwl) - { - action = body.sub(ugu+1,nwl); - action.trim(); - action.upper(); - } - - return true; -} - -bool TMailer_mask::build_key1(const TMail_message& msg, TToken_string& key, TString& action) const -{ - TString body; - FOR_EACH_ARRAY_ROW(msg, r, row) - body << *row << '\n'; - - const TString& subj = msg.subject(); - int lfile = LF_TAB; // Numero logico del file - if (isalpha(subj[0])) // Controlla se la tabella in realtà è comune ed aggiunge il simbolino % - { - TString4 para; para << '[' << LF_TABCOM << ']'; - if (body.find(para) > 0) - lfile = LF_TABCOM; - } - else - lfile = atoi(subj); - - return build_key1(lfile, body, key, action); -} - -void TMailer_mask::find_redundant_messages() -{ - // Elenco dei records (chiavi primarie) già processati (virtualmente) - TAssoc_array andreotti; - - TSheet_field& sf = sfield(F_MESSAGES); - TString subj, body, action; - TToken_string key1; - - // Scorro tutti i messaggi non ancora elaborati - FOR_EACH_SHEET_ROW_BACK(sf, nrow, row) if (row->get_char(0) <= ' ') - { - row->get(sf.cid2index(F_BODY), body); - if (body.find("[Transaction]") < 0) // Scarto i messaggi che non siano transazioni - { - row->add("F", 0); // Messaggio farlocco! - continue; - } - - row->get(sf.cid2index(F_SUBJECT), subj); - - int lfile = LF_TAB; // Numero logico del file - if (isalpha(subj[0])) // Controlla se la tabella in realtà è comune ed aggiunge il simbolino % - { - TString4 para; para << '[' << LF_TABCOM << ']'; - if (body.find(para) > 0) - lfile = LF_TABCOM; - } - else - lfile = atoi(subj); - - if (build_key1(lfile, body, key1, action)) - { - if (andreotti.is_key(key1) && action != "INSERT") // Non considero ridondanti gli inserimenti! - row->add("R", 0); // Messaggio ridondante! - else - andreotti.add(key1); // Messaggio da processare! - } - } -} - -void TMailer_mask::log(const char* text) -{ - TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); - TViswin& vv = bf.vis_win(); - - if (text && *text) - { - const struct tm* d = xvt_time_now(); - TString256 msg; - msg.format("- %02d-%02d-%04d %02d:%02d:%02d %s", - d->tm_mday, d->tm_mon+1, 1900+d->tm_year, - d->tm_hour, d->tm_min, d->tm_sec, - text); - vv.add_line(msg); - } - else - { - vv.add_line(""); - vv.goto_end(); - } -} - -void TMailer_mask::save_all_lines() -{ - if (_mail_semaphore != 0) - return; - _mail_semaphore = 1; - - TString msg; - - log(TR("Inizio elaborazione")); - - find_redundant_messages(); - - bool one_saved = false; - TSheet_field& sf = sfield(F_MESSAGES); - FOR_EACH_SHEET_ROW(sf, nrow, row) - { - msg.format("Messaggio %d ", nrow+1); - const char mark = *row->get(0); - - if (mark == 'X') - msg << "ignorato in quanto già elaborato"; else - if (mark == 'R') - { - msg << "ignorato in quanto ridondante"; - row->add("X", 0); // Marcalo come elaborato comunque - } else - if (mark == 'F') - { - msg << "ignorato in quanto in formato errato"; - row->add("X", 0); // Marcalo come elaborato comunque - } - - if (mark <= ' ') - { - TString body; row->get(sf.cid2index(F_BODY), body); - if (body.find("[Transaction]") >= 0) - { - const int err = save_sheet_line(nrow); - if (err == NOERR) - { - msg << TR("elaborato con successo"); - one_saved = true; - } else - if (err == NOT_GEST) - { - const TMask& m = sf.sheet_mask(); - msg << TR("definire il programma gestore del file ") << m.get(F_SUBJECT); - } - else - { - msg << TR("non elaborato a causa di un errore (n.ro ") << err << ')'; - if (_sequential) - break; - } - } - else - msg << TR("ignorato in quanto transazione non riconosciuta"); - } - log(msg); - } - - log(TR("Fine elaborazione")); - log(""); - - sf.force_update(); // Fai apparire tutte le X - - TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); - enable(DLG_DELLOG, bf.lines() > 0); - enable(DLG_DELREC); - -#ifdef DBG - if (one_saved) - one_saved = yesno_box("Si desidera eliminare i messaggi processati?"); -#endif - - _mail_semaphore = 0; - if (one_saved) - { - test_delete(); - fill_messages(); - } -} - -void TMailer_mask::exec_scripts() -{ - TSheet_field& sf = sfield(F_SCRIPTS); - if (_mail_semaphore != 0 || sf.items()== 0) - return; - _mail_semaphore = 1; - - TString cmd, des; - FOR_EACH_SHEET_ROW(sf, nrow, row) if (row->starts_with("X")) - { - row->get(1, cmd); - if (cmd.full()) - { - row->get(2, des); - log(des.full() ? des : cmd); - TExternal_app app(cmd); - const long ret = app.run(false, true, false); - if (ret != 0) - { - TString msg; msg.format(FR("Errore %ld nell'esecuzione di %s"), ret, (const char*)cmd); - log(msg); - } - } - } - - log(""); - - _mail_semaphore = 0; -} - -bool TMailer_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) -{ - switch (o.dlg()) - { - case F_TIMER: - if (e == fe_init || e == fe_modify) - { - if (_timer_id != XVT_TIMER_ERROR) - { - xvt_timer_destroy(_timer_id); - _timer_id = XVT_TIMER_ERROR; - } - _interval = atol(o.get()); - - if (_interval > 0) - { - _timer_id = xvt_timer_create(win(), 1000L); - _secs = 0L; - if (_timer_id == XVT_TIMER_ERROR) - return error_box("Impossibile impostare il timer"); - } - } - break; - case F_MESSAGES: - if (e == fe_init) - { - if (!field(F_SERVER).empty() && - !field(F_USER).empty() && - !field(F_PASSWORD).empty()) - fill_messages(); - } else - if (e == se_query_add) - { - auto_save_all(true); - return false; - } - break; - case DLG_USER: - if (e == fe_button) - { - int err = 0; - if (!save_sheet_line(err)) - { - if (err == NOT_TRANS) - message_box(TR("Messaggio ignorato: transazione non riconosciuta")); - else - if (err == NOT_GEST) - { - TSheet_field& sf = sfield(F_MESSAGES); - TMask& m = sf.sheet_mask(); - error_box(FR("Definire il programma gestore del file %s"), (const char*)m.get(F_SUBJECT)); - } - else - message_box(FR("Messaggio non elaborato a causa di un errore (n.ro %d)"), err); - } - - } - break; - case DLG_SAVEREC: - if (e == fe_button && jolly == 0) - { - if (curr_page() == 0) - save_all_lines(); - else - save(); - } - break; - case DLG_DELREC: - if (e == fe_button) - { - if (jolly == 0) - { - test_delete(); - fill_messages(); - return false; - } - } - break; - case F_FILE: - if (jolly == 3) - { - if (e == fe_button) - { - TMask& m = o.mask(); - TArray_sheet sht(-1,-1,-4,-4,TR("Selezione archivio"), HR("Codice@6R|Descrizione archivio@70")); - const TPrefix& pref = prefix(); - const int total = pref.items(); - if (total > 0) - { - TWait_cursor hourglass; - for (int i = LF_USER; i < total; i++) - { - TToken_string* row = new TToken_string; - *row << i; - row->add(pref.description(*row)); - sht.rows_array().add(row); - } - sht.select(m.get_int(o.dlg()) - LF_USER); - } - if (sht.run() == K_ENTER) - m.set(o.dlg(), sht.selected() + LF_USER); - } - } - break; - case F_EXPR: - if (jolly == 3) - { - if (e == fe_modify || e == fe_close) - { - TAutomask& m = (TAutomask&)o.mask(); - const int num = m.get_int(F_FILE); - TFilter_expr expr(m, num, o.get()); - return expr.error() == 0; - } - } - break; - case DLG_DELLOG: - if (e == fe_button) - { - TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); - TViswin& vv = bf.vis_win(); - vv.destroy_lines(); - } - break; - case DLG_PRINT: - if (e == fe_button) - { - TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); - TViswin& vv = bf.vis_win(); - vv.text().print(); - return false; // Don't close - } - break; - default: - break; - } - - _last_use = clock(); - - return true; -} - -void TMailer_mask::save_sheet(TConfig& ini, short dlg, const char* var) const -{ - TSheet_field& sf = sfield(dlg); - FOR_EACH_SHEET_ROW(sf, r, row) - ini.set(var, *row, NULL, true, r); -} - -void TMailer_mask::load_sheet(TConfig& ini, short dlg, const char* var) -{ - TSheet_field& sf = sfield(dlg); - sf.destroy(); - for (int r = 0; ini.exist(var, r); r++) - sf.row(r) = ini.get(var, NULL, r); -} - -void TMailer_mask::auto_save_all(bool manual) -{ - if (_mail_semaphore == 0) - { - TSheet_field& sf = sfield(F_MESSAGES); - test_delete(); - if (manual || sf.empty()) - fill_messages(); - if (_interval > 0 && sf.items() > 0) - save_all_lines(); - - exec_scripts(); - } - else - NFCHECK("Can't save locked mail"); -} - -bool TMailer_mask::unattended() const -{ - if (!xvt_vobj_is_focusable(win())) - return true; - - RCT r; xvt_vobj_get_outer_rect(TASK_WIN, &r); - if (r.bottom - r.top < 64) - return true; // Finestra principale iconizzata - - return (clock()-_last_use) > 10*CLOCKS_PER_SEC; -} - -long TMailer_mask::handler(WINDOW win, EVENT* ep) -{ - if (ep->type == E_TIMER && ep->v.timer.id == _timer_id) - { - _secs++; - if (_secs >= _interval) - { - _secs = 0L; - if (_mail_semaphore == 0 && unattended()) - auto_save_all(false); - } - return 0L; - } - return TAutomask::handler(win, ep); -} - -void TMailer_mask::save() const -{ - TConfig ini(CONFIG_DITTA, "MailTransactions"); - ini.remove_all(); - - ini.set("Server", get(F_SERVER)); - ini.set("User", get(F_USER)); - ini.set("Password", encode(get(F_PASSWORD))); - ini.set("Timer", get(F_TIMER)); - ini.set("Log", get(F_TRACKING)); - ini.set("Backup", get(F_BACKUP)); - ini.set("DelCancel", get(F_DELCANCEL)); - - save_sheet(ini, F_ADDRESSES, "Recipient"); - save_sheet(ini, F_PARAMS, "Filter"); - save_sheet(ini, F_SCRIPTS, "Script"); -} - -void TMailer_mask::load() -{ - TConfig ini(CONFIG_DITTA, "MailTransactions"); - - set(F_SERVER, ini.get("Server")); - set(F_USER, ini.get("User")); - set(F_PASSWORD, decode(ini.get("Password"))); - set(F_TIMER, ini.get_int("Timer")); - set(F_TRACKING, ini.get("Log")); - set(F_BACKUP, ini.get("Backup")); - set(F_DELCANCEL,ini.get("DelCancel")); - - load_sheet(ini, F_ADDRESSES, "Recipient"); - load_sheet(ini, F_PARAMS, "Filter"); - load_sheet(ini, F_SCRIPTS, "Script"); - - _sequential = ini.get_bool("StopOnError", "ba7"); -} - -TMailer_mask::TMailer_mask() - : TAutomask("ba7100a"), _timer_id(XVT_TIMER_ERROR), _mail_semaphore(0), _last_use(0) -{ - load(); - - const bool is_super = user() == ::dongle().administrator(); - enable(-G_SUPERUSER, is_super); -} - -TMailer_mask::~TMailer_mask() -{ - if (_timer_id != XVT_TIMER_ERROR) - { - xvt_timer_destroy(_timer_id); - _timer_id = XVT_TIMER_ERROR; - } - save(); -} - -/////////////////////////////////////////////////////////// -// TMailer -/////////////////////////////////////////////////////////// - -const char* const appname = TR("Postino"); - -class TMailer : public TSkeleton_application -{ -protected: - virtual bool create(); - virtual void main_loop(); -}; - -bool TMailer::create() -{ - if (xvt_vobj_get_attr(NULL_WIN, ATTR_APPL_ALREADY_RUNNING)) - { - TString msg; msg.format(FR("%s già in esecuzione!"), appname); - xvt_dm_popup_error(msg); - return false; - } - return TSkeleton_application::create(); -} - -void TMailer::main_loop() -{ - WINDOW tray = xvt_trayicon_create(TASK_WIN, 9013, appname); // CampoServer.ico - - open_files(LF_USER, 0); - TMailer_mask mm; - - if (tray != NULL_WIN) - { - // Se il postino è a tutto schermo lo minimizzo - RCT rct_screen, rct_postman; - xvt_vobj_get_outer_rect(SCREEN_WIN, &rct_screen); - xvt_vobj_get_outer_rect(TASK_WIN, &rct_postman); - if (xvt_rect_get_width(&rct_postman) >= xvt_rect_get_width(&rct_screen)-64) - xvt_vobj_set_visible(TASK_WIN, FALSE); - } - - mm.run(); - - xvt_trayicon_destroy(tray); -} - -int ba7100(int argc, char* argv[]) -{ - long style = xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_STYLE); - style |= WSF_NO_TASKBAR; - xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_STYLE, style); - - TMailer app; - app.run(argc, argv, appname); - return 0; -} +#define XVT_INCL_NATIVE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ba7.h" +#include "ba7100a.h" +#define NOT_TRANS -883 +#define NOT_GEST -884 + +/////////////////////////////////////////////////////////// +// TConfig utilities +/////////////////////////////////////////////////////////// + +/* Obsolete +static const TString& set_ini_var(int cfg, const char* para, const char* var, const char* val) +{ + TConfig ini(cfg, para); + const TString& prev = ini.get(var); + if (val != NULL) + ini.set(var, val); + if (prev.blank()) + return EMPTY_STRING; + TString& tmp = get_tmp_string(); + tmp = prev; + return tmp; +} + +inline const TString& get_ini_var(int cfg, const char* para, const char* var) +{ return ini_get_string(cfg, para, var); } +*/ + +/////////////////////////////////////////////////////////// +// TMail_box +/////////////////////////////////////////////////////////// + +class TMail_box : public TSocketClient +{ + unsigned long _connection; + +public: + bool default_params(TString& server, TString& user,TString& password); + + bool logon(const char* server = NULL, + const char* usr = NULL, const char* pwd = NULL); + virtual bool ok() const { return _connection != NULL; } + + bool list(TString_array& a); + int get(TMail_messages& m); + bool remove(const char* id); + + void logoff(); + + TMail_box(); + ~TMail_box(); +}; + +bool TMail_box::default_params(TString& server, TString& user,TString& password) +{ + bool ok = true; + if (server.blank()) + { + server = ini_get_string(CONFIG_INSTALL, "Server", "POP3"); + if (server.empty()) + ok = false; + } + if (user.blank()) + user = ::user(); + if (password.blank()) + { + const TString& pwd = cache().get(LF_USER, user).get("PASSWORD"); + password = ::decode(pwd); + } + return ok; +} + +bool TMail_box::logon(const char* ser, const char* usr, const char* pwd) +{ + if (_connection) + logoff(); + + if (!IsOk()) + return error_box(TR("Impossibile inizializzare il client POP3")); + + TString server(ser); + TString user(usr); + TString password(pwd); + if (!default_params(server, user, password)) + return error_box(TR("E' necessario specificare un server POP3, un utente ed una password")); + + TString msg; + msg << TR("Connessione al server POP3 ") << server; + xvtil_statbar_set(msg); + + _connection = QueryConnection("110", server); + if (_connection != 0) + { + msg.cut(0) << TR("Connesso al server POP3 ") << server; + xvtil_statbar_set(msg); + + TString buf(255); + ReadLine(_connection, buf); + if (buf[0] != '+') + return error_box(FR("Il server POP3 %s non risponde. Risultato:\n'%s'"), + (const char*)server, (const char *)buf); + + buf = "USER "; buf << user << "\r\n"; + WriteLine(_connection, buf); + TString req = buf; + ReadLine(_connection, buf); + if (buf[0] != '+') + return error_box(FR("Il server POP3 %s non accetta l'utente %s\nRichiesta : %sRisultato : %s"), + (const char*)server, (const char*)user, (const char *) req, (const char *)buf); + + buf = "PASS "; buf << password << "\r\n"; + WriteLine(_connection, buf); + req = buf; + ReadLine(_connection, buf); + if (buf[0] != '+') + return error_box(FR("Il server POP3 %s non accetta la password dell'utente %s\nRichiesta : %sRisultato : %s"), + (const char*)server, (const char*)user, (const char *) req, (const char *)buf); + } + else + return error_box(FR("Impossibile contattare il server POP3 %s"), + (const char*)server); + + return true; +} + +void TMail_box::logoff() +{ + if (_connection) + { + WriteLine(_connection, "QUIT\r\n"); + RemoveConnection(_connection); + _connection = NULL; + } +} + +bool TMail_box::list(TString_array& a) +{ + bool ok = _connection != NULL; + if (ok) + { + TString buf; + buf = "LIST\r\n"; + WriteLine(_connection, buf); + ReadLine(_connection, buf); + ok = buf[0] == '+'; + while (ok) + { + if (!ReadLine(_connection, buf)) + break; // Unexpected EOF + if (buf[0] == '.') + break; + int pos = buf.find(' '); + if (pos > 0) + buf.cut(pos); + a.add(buf); + } + } + return ok; +} + +HIDDEN int str2month(const char* str) +{ + const char* const mese[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + int m; + for (m = 11; m > 0; m--) + { + if (xvt_str_compare_ignoring_case(str, mese[m]) == 0) + break; + } + return m+1; +} + +enum EncodingType { enc_plain_text, enc_quoted_printable, enc_base64 }; + +int TMail_box::get(TMail_messages& m) +{ + // Lista dei caratteri validi + const char* const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+*"; + + // Lista per decodifica dei caratteri validi + char Deco64[256]; + memset(Deco64, ' ', sizeof(Deco64)); + + for (int i = 0; Base64[i]; i++) + Deco64[Base64[i]] = i; + TString_array a; + list(a); + + TString buf, boundary, msg_line; + + m.destroy(); + FOR_EACH_ARRAY_ROW(a, r, row) + { + TMail_message* msgptr = new TMail_message(user()); + m.add(msgptr); + TMail_message& msg = *msgptr; + + buf = "RETR "; buf << *row << "\r\n"; + WriteLine(_connection, buf); + ReadLine(_connection, buf); + bool ok = buf[0] == '+'; + EncodingType encoding = enc_plain_text; + bool in_body = false; + bool in_section = false; + bool buf_already_read = false; + boundary.cut(0); + + while (ok) + { + if (!buf_already_read) + { + if (!ReadLine(_connection, buf)) + { + ok = false; + break; // Unexpected EOF + } + } + else + buf_already_read = false; + if (buf[0] == '.') + { + buf.ltrim(1); + if (buf.blank()) + break; + } + if (in_body) + { + if (buf[0] == '-' && boundary.not_empty() && buf.find(boundary) >= 0) + break; // Ignora sezioni di attachment + + switch (encoding) + { + case enc_base64: + { + unsigned val = 0; + int bits = 0; + msg_line.cut(0); + for (const char* s = buf; *s && *s != '='; s++) + { + if (*s==0x0A || *s==0x0D || *s==0x20 || *s==0x09) + continue; // Salta eventuali blanks + val <<= 6; + val |= Deco64[*s]; + bits += 6; + if (bits >= 8) + { + const char c = char((val >> (bits - 8)) & 0xFF); + msg_line << c; + bits -= 8; + } + } + msg.add_line(msg_line); + } + break; + case enc_quoted_printable: + { + msg_line.cut(0); + for (const char* s = buf; *s; s++) + { + if (*s == '=') + { + s++; + if (*s >= ' ') + { + int c; sscanf(s, "%2X", &c); + msg_line << char(c); + s++; + } + } + else + msg_line << *s; + } + msg.add_line(msg_line); + } + break; + default: + buf.rtrim(); + msg.add_line(buf); + break; + } + } + else + { + if (boundary.not_empty()) + { + if (buf.blank()) + { + in_body = in_section; + } + else + { + if (buf.find(boundary) >= 0) + in_section = true; + } + } + else + { + if (buf.blank()) + { + in_body = true; + continue; + } + } + + if (buf.compare("From:", 5, true) == 0) + { + buf.ltrim(6); buf.trim(); + msg.set_sender(buf); + continue; + } + if (buf.compare("To:", 3, true) == 0) + { + buf.ltrim(4); buf.trim(); + msg.add_recipient(buf); + continue; + } + if (buf.compare("Cc:", 3, true) == 0) + { + buf.ltrim(4); buf.trim(); + msg.add_copy_recipient(buf); + continue; + } + if (buf.compare("Subject:", 8, true) == 0) + { + buf.ltrim(9); buf.trim(); + msg.set_subject(buf); + continue; + } + if (buf.compare("Date:", 5, true) == 0) + { + TToken_string d(buf.mid(6), ' '); d.trim(); + int giorno = d.get_int(1); + int mese = str2month(d.get()); + int anno = d.get_int(); + if (anno < 100) anno += 2000; + TString16 ora = d.get(); + buf.cut(0); + buf << anno << '/' << mese << '/' << giorno << ' ' << ora; + msg.set_date_time(buf); + continue; + } + if (buf.compare("Content-Transfer-Encoding:", 26, true) == 0) + { + if (buf.find("base64") > 0) + encoding = enc_base64; else + if (buf.find("quoted-printable") > 0) + encoding = enc_quoted_printable; + continue; + } + if (buf.compare("Content-Type:", 13, true) == 0) + { + int bnd = buf.find("oundary="); // Funziona per Boundary e boundary + if (bnd < 0) + { + ReadLine(_connection, buf); + bnd = buf.find("oundary="); + if (bnd < 0) + buf_already_read = true; + } + if (bnd > 0) + { + const int apicia = buf.find('"', bnd); + const int apicic = buf.find('"', apicia+1); + if (apicia > 0 && apicic > apicia) + boundary = buf.sub(apicia+1, apicic); + } + continue; + } + } + } + } + return m.items(); +} + +bool TMail_box::remove(const char* id) +{ + bool ok = _connection != NULL; + if (ok) + { + TString buf; + buf << "DELE " << id << "\r\n"; + WriteLine(_connection, buf); + ReadLine(_connection, buf); + ok = buf[0] == '+'; + } + return ok; +} + +TMail_box::TMail_box() : _connection(NULL) +{ +} + +TMail_box::~TMail_box() +{ + logoff(); +} + +/////////////////////////////////////////////////////////// +// TFilter_expr +/////////////////////////////////////////////////////////// + +class TFilter_expr : public TExpression +{ + TAutomask& _mask; + +protected: + virtual bool print_error(const char* msg) const; + +public: + TFilter_expr(TAutomask& m, int logicnum, const char* expr); + virtual ~TFilter_expr() { } +}; + +bool TFilter_expr::print_error(const char* msg) const +{ + return _mask.error_box(msg); +} + +TFilter_expr::TFilter_expr(TAutomask& m, int logicnum, const char* expr) + : _mask(m) +{ + bool ok = set(expr, _strexpr); + if (ok) + { + if (logicnum < LF_USER || logicnum >= prefix().items()) + logicnum = LF_TABCOM; // Niente errori fatali, se possibile + + const TRectype rec(logicnum); + + for (int i = 0; i < numvar(); i++) + { + const TFixed_string name(varname(i)); + int num = logicnum; + bool ok = rec.exist(name); + + if (!ok) + { + const TFieldref f(name, 0); + int num = table2logic(f.id()); + const TRectype join(num); + ok = join.exist(f.name()); + } + if (!ok) + { + _error = 883; + TString msg; + msg.format(FR("Il campo %s non appartiene al file %d"), varname(i), logicnum); + print_error(msg); + break; + } + } + } +} + + +/////////////////////////////////////////////////////////// +// TMailer_mask +/////////////////////////////////////////////////////////// + +class TMailer_mask : public TAutomask +{ + long _timer_id; + long _secs; + long _interval; + int _mail_semaphore; + TMail_messages _box; + bool _sequential; + clock_t _last_use; + + TString_array _key1; // Elenco dei campi della chiave principale dei files + TAssoc_array _apps; // Elenco delle applicazioni per processare i files + +protected: + virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); + virtual long handler(WINDOW win, EVENT* ep); + void log(const char* text); + +protected: + bool file2app(const TString& file, TString& app) const; + void expand_tabs(TMail_message& str, const int tab = 8) const; + + void save_sheet(TConfig& ini, short dlg, const char* var) const; + void load_sheet(TConfig& ini, short dlg, const char* var); + + TToken_string& get_key1(int lf) const; + bool build_key1(int lf, const TString& body, TToken_string& key, TString& action) const; + bool build_key1(const TMail_message& msg, TToken_string& key, TString& action) const; + void find_redundant_messages(); + + void track(const TMail_message& msg, const TString& app, const TString& action, int err); + int exec_app(const TString& appname, TMail_message & msg, TToken_string & sh_row); + void scan_ini_files(const char* dir, TString_array& result, int level) const; + void scan_dir(const TFilename& dir, TMail_messages& box) const; + bool unattended() const; + +public: + void test_delete(); + void fill_messages(); + int save_sheet_line(int line = -1); + void save_all_lines(); + void exec_scripts(); + void auto_save_all(bool manual); + + void save() const; + void load(); + + TMailer_mask(); + virtual ~TMailer_mask(); +}; + +void TMailer_mask::test_delete() +{ + if (_mail_semaphore != 0) + return; + _mail_semaphore = 1; + TWait_cursor hourglass; + + xvtil_statbar_set(TR("Eliminazione messaggi...")); + do_events(); + + TSheet_field& sf = sfield(F_MESSAGES); + const int sender_pos = sf.cid2index(F_SENDER); + const int mailer_pos = sf.cid2index(F_MAILER); + const int msgid_pos = sf.cid2index(F_ID); + TString4 mailer; + TString id; + + TMail_messages mapidel; // Lista dei messaggi MAPI da cancellare + + TMail_box mailbox; + FOR_EACH_SHEET_ROW_BACK(sf, nrow, row) if (*row->get(0) == 'X') + { + row->get(mailer_pos, mailer); + row->get(msgid_pos, id); + bool deleted = false; + if (mailer == "POP3") + { + if (!mailbox.ok()) + { + if (!mailbox.logon(get(F_SERVER), get(F_USER), get(F_PASSWORD))) + break; + } + deleted = mailbox.remove(id); + } else + if (mailer == "CNP") + { + TFilename file; + row->get(sender_pos, file); // Cartella di provenienza + file.add(id); + file.ext("ini"); + deleted = file.fremove(); + } else + if (mailer == "MAPI") + { + TMail_message* msg = new TMail_message(""); + msg->set_id(id); + mapidel.add(msg); + deleted = true; + } + if (deleted) + { + _box.destroy(nrow, true); + sf.destroy(nrow, false); + } + else + { + TString err = TR("Impossibile cancellare il messaggio"); + err << ' ' << id; + xvtil_statbar_set(err); + do_events(); + beep(2); // Error sound + } + } + if (mailbox.ok()) + mailbox.logoff(); + + if (mapidel.items() > 0) + { + xvtil_statbar_set(TR("Eliminazione messaggi MAPI...")); + do_events(); + mapidel.remove(); + } + + sf.force_update(); + + xvtil_statbar_set(TR("Pronto")); + do_events(); + _mail_semaphore = 0; +} + +void TMailer_mask::expand_tabs(TMail_message& msg, const int tab) const +{ + const int items = msg.items(); + for (int n = 0; n < items; n++) + { + TString & str = msg.row(n); + int start = 0; + + for (int i = 0; str[i]; i++) + { + switch(str[i]) + { + case '\n': + case '\r': + start = i+1; + break; + case '\t': + { + const int t = tab - ((i-start) % tab) - 1; + str[i] = ' '; + if (t > 0) + { + TString80 spac; spac.spaces(t); + str.insert(spac, i+1); + i += t; + } + } + break; + default: + break; + } + } + } +} + +void TMailer_mask::scan_ini_files(const char* dir, TString_array& result, int level) const +{ + TFilename mask = dir; mask.add("*.ini"); + + SLIST files = xvt_fsys_list_files("ini", mask, FALSE); + for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e)) + { + const char* fn = xvt_slist_get(files, e, NULL); + result.add(fn); + } + xvt_slist_destroy(files); + + if (level == 0) + { + mask = dir; mask.add("*"); + files = xvt_fsys_list_files(DIR_TYPE, mask, TRUE); + const int tot = xvt_slist_count(files); + if (tot > 0) + { + TProgind pi(tot, TR("Elaborazione cartelle transazioni"), true, true); + for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e)) + { + if (!pi.addstatus(1)) + break; + const char* fn = xvt_slist_get(files, e, NULL); + if (dexist(fn)) + scan_ini_files(fn, result, level+1); + } + } + xvt_slist_destroy(files); + } +} + +void TMailer_mask::scan_dir(const TFilename& dir, TMail_messages& box) const +{ + box.destroy(); + TString_array msg; + scan_ini_files(dir, msg, 0); + + TString subject, text, strdata; + TToken_string id(_MAX_FNAME, '_'); + FOR_EACH_ARRAY_ROW(msg, r, row) + { + const int size = fsize(*row); + if (size > 64 && size < 48*1024) + { + char* buffer = text.get_buffer(size); + TScanner scanner(*row); + + memset(buffer, 0 , size); + scanner.read(buffer, size); + buffer[size] = '\0'; + + if (text.starts_with("[TRANSACTION]")) // Zucchetti maiuscolo! + { + const char* maiusc[] = { "[TRANSACTION]", "ACTION=", "FIRM=", "MODE=I", "USER=", "RESULT=", "ERRORMSG=", NULL}; + const char* minusc[] = { "[Transaction]", "Action=", "Firm=", "Mode=A", "User=", "Result=", "Error= ", NULL}; + for (int w = 0; maiusc[w]; w++) + { + const int i = text.find(maiusc[w]); + if (i >= 0) + text.overwrite(minusc[w], i); + } + } + + subject.cut(0); + if (text.find("[Transaction]") >= 0) + { + int parc = text.find(']'); // fine primo paragrafo + if (parc > 0) + { + int para = text.find('[', parc+1); + if (para > 0) + { + parc = text.find(']', para+1); + if (parc > 0) + subject = text.sub(para+1, parc); + } + } + } + if (subject.full()) + { + FILE_SPEC fs; xvt_fsys_convert_str_to_fspec(*row, &fs); + + TMail_message* msg = new TMail_message(user(), subject, text, fs.dir.path); + msg->set_id(id = fs.name); + + if (id.items() == 3) // Nome file in formato YYMMDD_HHMMSS_NN.ini + { + strdata = id.get(0); strdata.insert("20"); + const TDate data(strdata); + const long hhmmss = id.get_long(1); + msg->set_date_time(data, hhmmss); + } + else + { + const time_t dt = xvt_fsys_get_file_attr(&fs, XVT_FILE_ATTR_MTIME); + const struct tm* t = localtime(&dt); + msg->set_date_time(TDate(t->tm_mday, t->tm_mon, t->tm_year+1900), + t->tm_hour*10000 + t->tm_min*100 + t->tm_sec); + } + + box.add(msg); + } + } + } +} + +void TMailer_mask::fill_messages() +{ + if (_mail_semaphore != 0) + return; + _mail_semaphore = 1; + + disable(DLG_DELREC); + + TWait_cursor hourglass; + + TFilename server(get(F_SERVER)); + TString80 user(get(F_USER)); + TString80 password(get(F_PASSWORD)); + TMail_box mailbox; + if (mailbox.default_params(server, user, password)) + { + set(F_SERVER, server); + set(F_USER, user); + set(F_PASSWORD, password); + } + expand_sys_vars(server); + + int totmapi = 0; + + if (get_bool(F_MAPI)) + { + xvtil_statbar_set(TR("Ricezione messaggi MAPI...")); + do_events(); + totmapi = _box.get(); + + for (int i = 0; i < totmapi; i++) + { + TMail_message& msg = _box.msg(i); + const TString& subject = msg.subject(); + bool kill = msg.empty() || subject.blank() || subject.len() > 4; + if (!kill) + { + TString& line = msg.row(0); + int pos = line.find("[Transaction]"); + if (pos) + { + if (pos < 0) + kill = true; + else + line.ltrim(pos); + } + pos = line.find("-----"); + if (pos > 0) + line.cut(pos); + } + if (kill) // Not a Campo transaction + _box.destroy(i); + } + _box.pack(); + totmapi = _box.items(); + } + + TString4 mailer; + if (isalpha(server[0]) && server[1] == ':' && is_slash(server[2]) && server.exist()) + { + mailer = "CNP"; + xvtil_statbar_set(TR("Ricezione messaggi CNP ...")); + do_events(); + scan_dir(server, _box); + } + else + { + mailer = "POP3"; + if (server.full()) + { + xvtil_statbar_set(TR("Ricezione messaggi POP3...")); + do_events(); + mailbox.logon(server, user, password); + mailbox.get(_box); + mailbox.logoff(); + } + } + + TSheet_field& sf = sfield(F_MESSAGES); + sf.destroy(); + TString mess; + FOR_EACH_ARRAY_ITEM(_box, m, obj) + { + TMail_message& msg = _box.msg(m); + TToken_string& row = sf.row(-1); + row.add(msg.sender(), sf.cid2index(F_SENDER)); + row.add(msg.date(), sf.cid2index(F_DATE)); + const real t = msg.time(); + row.add(t.string("@@:@@:@@"), sf.cid2index(F_TIME)); + row.add(msg.subject(), sf.cid2index(F_SUBJECT)); + expand_tabs(msg); + + mess.cut(0); + FOR_EACH_ARRAY_ROW(msg, i, msgrow) + { + mess << *msgrow; + if (mess.len() >= 1024) + { + mess.cut(1024); + break; + } + } + row.add(mess, sf.cid2index(F_BODY)); + if (m < totmapi) + { + row.add("MAPI", sf.cid2index(F_MAILER)); + row.add(msg.id(), sf.cid2index(F_ID)); + } + else + { + row.add(mailer, sf.cid2index(F_MAILER)); + if (mailer == "CNP") + row.add(msg.id(), sf.cid2index(F_ID)); + else + row.add(m-totmapi+1, sf.cid2index(F_ID)); + } + } + sf.force_update(); + + xvtil_statbar_set(TR("Pronto")); + + _mail_semaphore = 0; + return; +} + +bool TMailer_mask::file2app(const TString& file, TString& app) const +{ + bool ok = false; + + const TString* run = (const TString*)_apps.objptr(file); + if (run == NULL) + { + TString16 appname; appname << "Edit_" << file; + app = ini_get_string(CONFIG_DITTA, "ba7", appname); + if (app.empty()) + { + if (isdigit(file[0])) + { + const int filenum = atoi(file); + if (filenum >= LF_USER && filenum < prefix().items()) + { + TLocalisamfile isf(filenum); + ok = isf.get_relapp(app); + } + } + else + { + const int len = file.len(); + if (len == 3 || (len == 4 && file[0] == '%')) + { + TTable table(file); + ok = table.get_relapp(app); + } else + if (len >= 4 && file[0] == '&') + { + TModule_table tabmod(file); + ok = tabmod.get_relapp(app); + } + } + } + else + ok = true; + + ((TMailer_mask*)this)->_apps.add(file, app); // Fool const + } + else + { + app = *run; + ok = app.full(); + } + return ok; +} + +bool is_incomplete(const TString& l) +{ + if (l[0] == '[') + return false; + + const char a = l.right(1)[0]; + if (a == '=') + return true; + + const int eq = l.find("= '"); + if (eq > 0 && eq < 20) + return a != '\''; + + return false; +} + +void adjust_long_lines(const TFilename& tmp) +{ + TFilename dst_name; dst_name.temp(); + ofstream dst(dst_name); + + bool adjusted = false; + + TScanner org(tmp); + while (true) + { + const TString& l = org.line(); + if (l.empty()) + break; + if (is_incomplete(l)) + { + adjusted = true; + dst << l; + org.line(); + char s = l[0]; + if (s == '\'' || s == '"') + { + char c = l.right(1)[0]; + while (c != '\'' && c != '"') + { + dst << l; + org.line(); + c = l.right(1)[0]; + } + } + else + dst << '\n'; + } + dst << l << '\n'; + } + org.close(); + dst.close(); + if (adjusted) + fcopy(dst_name, tmp); + dst_name.fremove(); +} + +void TMailer_mask::track(const TMail_message& msg, const TString& app, const TString& action, int err) +{ + const TString& fname = get(F_TRACKING); + + if (fname.full()) + { + const char fldsep = '\t'; + const char recsep = '\n'; + + ofstream log(fname, ios::app); + + log << msg.sender() << fldsep; + + log << msg.date() << fldsep; + const real t = msg.time(); + log << t.string("@@:@@:@@") << fldsep; + + TToken_string k1; + TString act; + build_key1(msg, k1, act); + log << k1.get(0) << fldsep; + + const int pipe = k1.find(k1.separator()); + k1.ltrim(pipe+1); + log << k1 << fldsep; + + log << app << fldsep << action << fldsep << err << fldsep; + + log << recsep; + } +} + +#ifdef WIN32 + +#include + +static int run_sync(const char* appname) +{ + int err = 0; + TString app, par; + app = appname; + + const int spc = app.find(' '); + if (spc > 0) + { + par = app.mid(spc+1); + par << " /uADMIN"; + + app.cut(spc); + if (app.find(".exe") < 0 && app.find(".bat") < 0) + app << ".exe"; + } + + SHELLEXECUTEINFO sei; memset(&sei, 0, sizeof(sei)); + sei.cbSize = sizeof(sei); + sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; + sei.lpVerb = ""; + sei.lpFile = app; + sei.lpParameters = par; + sei.nShow = SW_SHOWNORMAL; + if (::ShellExecuteEx(&sei)) + { + if (sei.hProcess != NULL) + { + ::WaitForSingleObject(sei.hProcess, 0); + ::CloseHandle(sei.hProcess); + } + else + err = EBADF; + } + else + err = ENOEXEC; + return err; +} + +#else + +static int run_sync(const char* appname) +{ + TExternal_app app(cmd); + return app.run(false, true, false); // Don't iconize (nor restore) the task window! +} + +#endif + +int TMailer_mask::exec_app(const TString& appname, TMail_message& msg, TToken_string & sh_row) +{ + int err = NOERR; + TString action; + if (appname.compare("sink", -1, true) == 0) + { + FOR_EACH_ARRAY_ROW(msg, r, row) + { + int s = row->find("\nAction"); + if (s > 0) + { + s = row->find('=', s); + const int e = row->find('\n', s); + action = row->sub(s+1, e); + action.trim(); + break; + } + } + } + else + { + TFilename tmp; tmp.temp("trn", "ini"); + if (tmp.full()) + { + ofstream outf(tmp); + const int items = msg.items(); + TString message; + for (int i = 0; i < items; i++) + { + message = msg.row(i); + message.replace('\r', '\n'); + outf << message; + } + outf.close(); + adjust_long_lines(tmp); + + TConfig ini(tmp, "Transaction"); + ini.set("From", msg.sender()); + action = ini.get("Action"); + } + + TString command_line(appname); + command_line << " /i" << tmp; + err = run_sync(command_line); + xvt_sys_sleep(1000); + + if (err == NOERR) + { + TConfig ini(tmp, "Transaction"); + if (ini.get("Result").compare("OK", -1, true) == 0 || + ini.get("Action").compare("RUN", -1, true) == 0) + err = 0; + else + if (get_bool(F_DELCANCEL) && ini.get("Result").compare("Cancel", -1, true) == 0) + err = 0; + else + err = ini.get_int("Error"); + + TFilename backup = get(F_BACKUP); + expand_sys_vars(backup); + if (backup.exist()) + { + const TSheet_field& sf = sfield(F_MESSAGES); + + TString id; + TFilename file; + sh_row.get(sf.cid2index(F_ID), id); + sh_row.get(sf.cid2index(F_SENDER), file); // Cartella di provenienza + file.add(id); + file.ext("ini"); + + TFilename dest = backup; + dest.add(file.name()); + fcopy(tmp, dest); + } + } + tmp.fremove(); + } + + track(msg, appname, action, err); + + return err; +} + +int TMailer_mask::save_sheet_line(int nrow) +{ + int err = NOERR; + TSheet_field& sf = sfield(F_MESSAGES); + TMask& m = sf.sheet_mask(); + + if (nrow < 0) + nrow = sf.selected(); + else + sf.update_mask(nrow); + + TToken_string& row = sf.row(nrow); + + const TString& msg = m.get(F_BODY); + if (msg.find("[Transaction]") < 0) + { + err = NOT_TRANS; + return false; // It's not a transaction + } + + TString subj = m.get(F_SUBJECT); + TIsam_handle logic = LF_TAB; + if (isalpha(subj[0])) // Controlla se la tabella in realtà è comune ed aggiunge il simbolino % + { + TString8 para; para << '[' << LF_TABCOM << ']'; + if (msg.find(para) > 0) + subj.insert("%"); + } + else + { + logic = atoi(subj); + if (logic == LF_TAB || logic == LF_TABCOM) + { + TString8 para; para << '[' << logic << ']'; + int pos = msg.find(para); + if (pos > 0) + { + pos = msg.find("\nCOD", pos+3); + if (pos > 0) + { + TToken_string line(msg.mid(pos, 10), '='); + line.strip_spaces(); + if (line.items() == 2) + { + subj = line.get(1); subj.cut(3); + if (logic == LF_TABCOM) + subj.insert("%"); + } + } + } + } + } + + TFilename appname; + if (!file2app(subj, appname)) // It hasn't a valid application + return err = NOT_GEST; + + TMail_message& full_msg = _box.msg(nrow); + err = exec_app(appname, full_msg, row); + if (err == _iskeynotfound) + { + TString & first_row = full_msg.row(0); + int pos = first_row.find("MODIFY"); + if (pos > 0) + { + first_row.overwrite("INSERT", pos); + err = exec_app(appname, full_msg, row); + } + } + + if (err == NOERR) + { + if (m.is_running()) + { + m.set(F_CHECKED, "X"); + m.stop_run(K_AUTO_ENTER); + } + else + { + row.add("X", 0); + sf.force_update(nrow); + } + } + + return err; +} + +TToken_string& TMailer_mask::get_key1(int lf) const +{ + TString_array& k = (TString_array&)_key1; // Fool constness + TToken_string* key = k.rowptr(lf); + if (key == NULL) + { + key = new TToken_string; // Creo una nuova entry + const RecDes& recd = prefix().get_recdes(lf); // Descrizione del record della testata + const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1 + for (int i = 0; i < kd.NkFields; i++) + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = recd.Fd[nf]; + key->add(rf.Name); + } + k.add(key, lf); + } + return *key; +} + +bool TMailer_mask::build_key1(int lf, const TString& body, TToken_string& key, TString& action) const +{ + key.format("%d", lf); + + TString16 field; // Nome del campo chiave + TString value; // Valore del campo chiave + + TToken_string& key1 = get_key1(lf); // Elenco dei campi chiave + FOR_EACH_TOKEN(key1, fld) + { + field = fld; field.insert("\n"); + const int start = body.find(field); + if (start < 0) + return false; + const int equal = body.find('=', start); + if (equal < 0) + return false; + const int stop = body.find('\n', equal); + if (stop < 0) + return false; + value = body.sub(equal+1, stop); + value.trim(); + if (value[0] == '"' && value.right(1) == "\"") // Toglie eventuali virgolette + { + value.rtrim(1); + value.ltrim(1); + } + key.add(value); + } + + const int act = body.find("\nAction"); + const int ugu = act > 0 ? body.find('=', act) : -1; + const int nwl = ugu > 0 ? body.find('\n', ugu) : -1; + if (act > 0 && ugu > act && ugu < nwl) + { + action = body.sub(ugu+1,nwl); + action.trim(); + action.upper(); + } + + return true; +} + +bool TMailer_mask::build_key1(const TMail_message& msg, TToken_string& key, TString& action) const +{ + TString body; + FOR_EACH_ARRAY_ROW(msg, r, row) + body << *row << '\n'; + + const TString& subj = msg.subject(); + int lfile = LF_TAB; // Numero logico del file + if (isalpha(subj[0])) // Controlla se la tabella in realtà è comune ed aggiunge il simbolino % + { + TString4 para; para << '[' << LF_TABCOM << ']'; + if (body.find(para) > 0) + lfile = LF_TABCOM; + } + else + lfile = atoi(subj); + + return build_key1(lfile, body, key, action); +} + +void TMailer_mask::find_redundant_messages() +{ + // Elenco dei records (chiavi primarie) già processati (virtualmente) + TAssoc_array andreotti; + + TSheet_field& sf = sfield(F_MESSAGES); + TString subj, body, action; + TToken_string key1; + + // Scorro tutti i messaggi non ancora elaborati + FOR_EACH_SHEET_ROW_BACK(sf, nrow, row) if (row->get_char(0) <= ' ') + { + row->get(sf.cid2index(F_BODY), body); + if (body.find("[Transaction]") < 0) // Scarto i messaggi che non siano transazioni + { + row->add("F", 0); // Messaggio farlocco! + continue; + } + + row->get(sf.cid2index(F_SUBJECT), subj); + + int lfile = LF_TAB; // Numero logico del file + if (isalpha(subj[0])) // Controlla se la tabella in realtà è comune ed aggiunge il simbolino % + { + TString4 para; para << '[' << LF_TABCOM << ']'; + if (body.find(para) > 0) + lfile = LF_TABCOM; + } + else + lfile = atoi(subj); + + if (build_key1(lfile, body, key1, action)) + { + if (andreotti.is_key(key1) && action != "INSERT") // Non considero ridondanti gli inserimenti! + row->add("R", 0); // Messaggio ridondante! + else + andreotti.add(key1); // Messaggio da processare! + } + } +} + +void TMailer_mask::log(const char* text) +{ + TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); + TViswin& vv = bf.vis_win(); + + if (text && *text) + { + const struct tm* d = xvt_time_now(); + TString256 msg; + msg.format("- %02d-%02d-%04d %02d:%02d:%02d %s", + d->tm_mday, d->tm_mon+1, 1900+d->tm_year, + d->tm_hour, d->tm_min, d->tm_sec, + text); + vv.add_line(msg); + } + else + { + vv.add_line(""); + vv.goto_end(); + } +} + +void TMailer_mask::save_all_lines() +{ + if (_mail_semaphore != 0) + return; + _mail_semaphore = 1; + + TString msg; + + log(TR("Inizio elaborazione")); + + find_redundant_messages(); + + bool one_saved = false; + TSheet_field& sf = sfield(F_MESSAGES); + FOR_EACH_SHEET_ROW(sf, nrow, row) + { + msg.format("Messaggio %d ", nrow+1); + const char mark = *row->get(0); + + if (mark == 'X') + msg << "ignorato in quanto già elaborato"; else + if (mark == 'R') + { + msg << "ignorato in quanto ridondante"; + row->add("X", 0); // Marcalo come elaborato comunque + } else + if (mark == 'F') + { + msg << "ignorato in quanto in formato errato"; + row->add("X", 0); // Marcalo come elaborato comunque + } + + if (mark <= ' ') + { + TString body; row->get(sf.cid2index(F_BODY), body); + if (body.find("[Transaction]") >= 0) + { + const int err = save_sheet_line(nrow); + if (err == NOERR) + { + msg << TR("elaborato con successo"); + one_saved = true; + } else + if (err == NOT_GEST) + { + const TMask& m = sf.sheet_mask(); + msg << TR("definire il programma gestore del file ") << m.get(F_SUBJECT); + } + else + { + msg << TR("non elaborato a causa di un errore (n.ro ") << err << ')'; + if (_sequential) + break; + } + } + else + msg << TR("ignorato in quanto transazione non riconosciuta"); + } + log(msg); + } + + log(TR("Fine elaborazione")); + log(""); + + sf.force_update(); // Fai apparire tutte le X + + TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); + enable(DLG_DELLOG, bf.lines() > 0); + enable(DLG_DELREC); + +#ifdef DBG + if (one_saved) + one_saved = yesno_box("Si desidera eliminare i messaggi processati?"); +#endif + + _mail_semaphore = 0; + if (one_saved) + { + test_delete(); + fill_messages(); + } +} + +void TMailer_mask::exec_scripts() +{ + TSheet_field& sf = sfield(F_SCRIPTS); + if (_mail_semaphore != 0 || sf.items()== 0) + return; + _mail_semaphore = 1; + + TString cmd, des; + FOR_EACH_SHEET_ROW(sf, nrow, row) if (row->starts_with("X")) + { + row->get(1, cmd); + if (cmd.full()) + { + row->get(2, des); + log(des.full() ? des : cmd); + TExternal_app app(cmd); + const long ret = app.run(false, true, false); + if (ret != 0) + { + TString msg; msg.format(FR("Errore %ld nell'esecuzione di %s"), ret, (const char*)cmd); + log(msg); + } + } + } + + log(""); + + _mail_semaphore = 0; +} + +bool TMailer_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) +{ + switch (o.dlg()) + { + case F_TIMER: + if (e == fe_init || e == fe_modify) + { + if (_timer_id != XVT_TIMER_ERROR) + { + xvt_timer_destroy(_timer_id); + _timer_id = XVT_TIMER_ERROR; + } + _interval = atol(o.get()); + + if (_interval > 0) + { + _timer_id = xvt_timer_create(win(), 1000L); + _secs = 0L; + if (_timer_id == XVT_TIMER_ERROR) + return error_box("Impossibile impostare il timer"); + } + } + break; + case F_MESSAGES: + if (e == fe_init) + { + if (!field(F_SERVER).empty() && + !field(F_USER).empty() && + !field(F_PASSWORD).empty()) + fill_messages(); + } else + if (e == se_query_add) + { + auto_save_all(true); + return false; + } + break; + case DLG_USER: + if (e == fe_button) + { + int err = 0; + if (!save_sheet_line(err)) + { + if (err == NOT_TRANS) + message_box(TR("Messaggio ignorato: transazione non riconosciuta")); + else + if (err == NOT_GEST) + { + TSheet_field& sf = sfield(F_MESSAGES); + TMask& m = sf.sheet_mask(); + error_box(FR("Definire il programma gestore del file %s"), (const char*)m.get(F_SUBJECT)); + } + else + message_box(FR("Messaggio non elaborato a causa di un errore (n.ro %d)"), err); + } + + } + break; + case DLG_SAVEREC: + if (e == fe_button && jolly == 0) + { + if (curr_page() == 0) + save_all_lines(); + else + save(); + } + break; + case DLG_DELREC: + if (e == fe_button) + { + if (jolly == 0) + { + test_delete(); + fill_messages(); + return false; + } + } + break; + case F_FILE: + if (jolly == 3) + { + if (e == fe_button) + { + TMask& m = o.mask(); + TArray_sheet sht(-1,-1,-4,-4,TR("Selezione archivio"), HR("Codice@6R|Descrizione archivio@70")); + const TPrefix& pref = prefix(); + const int total = pref.items(); + if (total > 0) + { + TWait_cursor hourglass; + for (int i = LF_USER; i < total; i++) + { + TToken_string* row = new TToken_string; + *row << i; + row->add(pref.description(*row)); + sht.rows_array().add(row); + } + sht.select(m.get_int(o.dlg()) - LF_USER); + } + if (sht.run() == K_ENTER) + m.set(o.dlg(), sht.selected() + LF_USER); + } + } + break; + case F_EXPR: + if (jolly == 3) + { + if (e == fe_modify || e == fe_close) + { + TAutomask& m = (TAutomask&)o.mask(); + const int num = m.get_int(F_FILE); + TFilter_expr expr(m, num, o.get()); + return expr.error() == 0; + } + } + break; + case DLG_DELLOG: + if (e == fe_button) + { + TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); + TViswin& vv = bf.vis_win(); + vv.destroy_lines(); + } + break; + case DLG_PRINT: + if (e == fe_button) + { + TBrowsefile_field& bf = (TBrowsefile_field&)field(F_LOG); + TViswin& vv = bf.vis_win(); + vv.text().print(); + return false; // Don't close + } + break; + default: + break; + } + + _last_use = clock(); + + return true; +} + +void TMailer_mask::save_sheet(TConfig& ini, short dlg, const char* var) const +{ + TSheet_field& sf = sfield(dlg); + FOR_EACH_SHEET_ROW(sf, r, row) + ini.set(var, *row, NULL, true, r); +} + +void TMailer_mask::load_sheet(TConfig& ini, short dlg, const char* var) +{ + TSheet_field& sf = sfield(dlg); + sf.destroy(); + for (int r = 0; ini.exist(var, r); r++) + sf.row(r) = ini.get(var, NULL, r); +} + +void TMailer_mask::auto_save_all(bool manual) +{ + if (_mail_semaphore == 0) + { + TSheet_field& sf = sfield(F_MESSAGES); + test_delete(); + if (manual || sf.empty()) + fill_messages(); + if (_interval > 0 && sf.items() > 0) + save_all_lines(); + + exec_scripts(); + } + else + NFCHECK("Can't save locked mail"); +} + +bool TMailer_mask::unattended() const +{ + if (!xvt_vobj_is_focusable(win())) + return true; + + RCT r; xvt_vobj_get_outer_rect(TASK_WIN, &r); + if (r.bottom - r.top < 64) + return true; // Finestra principale iconizzata + + return (clock()-_last_use) > 10*CLOCKS_PER_SEC; +} + +long TMailer_mask::handler(WINDOW win, EVENT* ep) +{ + if (ep->type == E_TIMER && ep->v.timer.id == _timer_id) + { + _secs++; + if (_secs >= _interval) + { + _secs = 0L; + if (_mail_semaphore == 0 && unattended()) + auto_save_all(false); + } + return 0L; + } + return TAutomask::handler(win, ep); +} + +void TMailer_mask::save() const +{ + TConfig ini(CONFIG_DITTA, "MailTransactions"); + ini.remove_all(); + + ini.set("Server", get(F_SERVER)); + ini.set("User", get(F_USER)); + ini.set("Password", encode(get(F_PASSWORD))); + ini.set("Timer", get(F_TIMER)); + ini.set("Log", get(F_TRACKING)); + ini.set("Backup", get(F_BACKUP)); + ini.set("DelCancel", get(F_DELCANCEL)); + + save_sheet(ini, F_ADDRESSES, "Recipient"); + save_sheet(ini, F_PARAMS, "Filter"); + save_sheet(ini, F_SCRIPTS, "Script"); +} + +void TMailer_mask::load() +{ + TConfig ini(CONFIG_DITTA, "MailTransactions"); + + set(F_SERVER, ini.get("Server")); + set(F_USER, ini.get("User")); + set(F_PASSWORD, decode(ini.get("Password"))); + set(F_TIMER, ini.get_int("Timer")); + set(F_TRACKING, ini.get("Log")); + set(F_BACKUP, ini.get("Backup")); + set(F_DELCANCEL,ini.get("DelCancel")); + + load_sheet(ini, F_ADDRESSES, "Recipient"); + load_sheet(ini, F_PARAMS, "Filter"); + load_sheet(ini, F_SCRIPTS, "Script"); + + _sequential = ini.get_bool("StopOnError", "ba7"); +} + +TMailer_mask::TMailer_mask() + : TAutomask("ba7100a"), _timer_id(XVT_TIMER_ERROR), _mail_semaphore(0), _last_use(0) +{ + load(); + + const bool is_super = user() == ::dongle().administrator(); + enable(-G_SUPERUSER, is_super); +} + +TMailer_mask::~TMailer_mask() +{ + if (_timer_id != XVT_TIMER_ERROR) + { + xvt_timer_destroy(_timer_id); + _timer_id = XVT_TIMER_ERROR; + } + save(); +} + +/////////////////////////////////////////////////////////// +// TMailer +/////////////////////////////////////////////////////////// + +const char* const appname = TR("Postino"); + +class TMailer : public TSkeleton_application +{ +protected: + virtual bool create(); + virtual void main_loop(); +}; + +bool TMailer::create() +{ + if (xvt_vobj_get_attr(NULL_WIN, ATTR_APPL_ALREADY_RUNNING)) + { + TString msg; msg.format(FR("%s già in esecuzione!"), appname); + xvt_dm_popup_error(msg); + return false; + } + return TSkeleton_application::create(); +} + +void TMailer::main_loop() +{ + WINDOW tray = xvt_trayicon_create(TASK_WIN, 9013, appname); // CampoServer.ico + + open_files(LF_USER, 0); + TMailer_mask mm; + + if (tray != NULL_WIN) + { + // Se il postino è a tutto schermo lo minimizzo + RCT rct_screen, rct_postman; + xvt_vobj_get_outer_rect(SCREEN_WIN, &rct_screen); + xvt_vobj_get_outer_rect(TASK_WIN, &rct_postman); + if (xvt_rect_get_width(&rct_postman) >= xvt_rect_get_width(&rct_screen)-64) + xvt_vobj_set_visible(TASK_WIN, FALSE); + } + + mm.run(); + + xvt_trayicon_destroy(tray); +} + +int ba7100(int argc, char* argv[]) +{ + long style = xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_STYLE); + style |= WSF_NO_TASKBAR; + xvt_vobj_set_attr(NULL_WIN, ATTR_WIN_PM_TWIN_STARTUP_STYLE, style); + + TMailer app; + app.run(argc, argv, appname); + return 0; +} diff --git a/ba/ba8300d.uml b/ba/ba8300d.uml index 0fc818d84..d39660ac0 100755 --- a/ba/ba8300d.uml +++ b/ba/ba8300d.uml @@ -1,35 +1,35 @@ #include "ba8300.h" -PAGE "Report" -1 -1 66 18 +PAGE "Report" -1 -1 68 18 -RADIO F_ORIENTATION 1 24 +RADIO F_ORIENTATION 1 26 BEGIN PROMPT 1 0 "@bOrientamento della carta" ITEM "0|Come da stampante" ITEM "1|Ritratto (Verticale)" - ITEM "2|Paesaggio (Orizzontale)" + ITEM "2|Paesaggio (Orizzont.)" END BOOLEAN F_PAGE_SPLIT BEGIN - PROMPT 26 1 "Suddividi una pagina su più fogli" + PROMPT 28 1 "Suddivisione pagina su più fogli" END BOOLEAN F_PAGE_MERGE BEGIN - PROMPT 26 2 "Raggruppa più pagine in un foglio" + PROMPT 28 2 "Raggruppa più pagine in un foglio" END BOOLEAN F_FONT_AUTO BEGIN - PROMPT 26 3 "Seleziona font della stampante" + PROMPT 28 3 "Seleziona font della stampante" MESSAGE FALSE ENABLE,F_FONT_SELECT|ENABLE,F_DY|ENABLE,F_DX MESSAGE TRUE DISABLE,F_FONT_SELECT|DISABLE,F_DY|DISABLE,F_DX END BOOLEAN F_SAVE_PRINTER BEGIN - PROMPT 26 4 "Memorizza ultima stampante utilizzata" + PROMPT 28 4 "Memorizzare stampante utilizzata" END NUMBER F_DX 2 diff --git a/ba/ba8500.cpp b/ba/ba8500.cpp index 1c42ebbd0..753761404 100755 --- a/ba/ba8500.cpp +++ b/ba/ba8500.cpp @@ -151,6 +151,24 @@ TReport* TKlarkKent_app::create_report(const char* name) const return r; } +static TVariant* str2var(const char* str) +{ + TVariant* var = NULL; + if (str && *str) + { + const int len = strlen(str); + if (len <= 8 && real::is_natural(str)) + var = new TVariant(atol(str)); else + if (len <= 15 && real::is_real(str)) + var = new TVariant(real(str)); + else + var = new TVariant(str); + } + else + var = new TVariant; + return var; +} + void TKlarkKent_app::main_loop() { TString_array arr; // Lista dei reports @@ -168,16 +186,7 @@ void TKlarkKent_app::main_loop() val = arg.mid(uguale+1); val.trim(); if (name.full()) { - TVariant* var = NULL; - if (val.full()) - { - if (real::is_real(val)) - var = new TVariant(real(val)); - else - var = new TVariant(val); - } - else - var = new TVariant; + TVariant* var = str2var(val); if (name[0] != '#') name.insert("#"); vars.add(name, var); @@ -193,16 +202,7 @@ void TKlarkKent_app::main_loop() TAssoc_array& inivars = ini.list_variables(); FOR_EACH_ASSOC_STRING(inivars, obj, key, str) { - TVariant* var = NULL; - if (str && *str) - { - if (real::is_real(str)) - var = new TVariant(real(str)); - else - var = new TVariant(str); - } - else - var = new TVariant; + TVariant* var = str2var(str); name = key; if (name[0] != '#') name.insert("#"); diff --git a/ba/f6.dir b/ba/f6.dir index 019c0edd6..d1d118a7b 100755 --- a/ba/f6.dir +++ b/ba/f6.dir @@ -1,3 +1,3 @@ 6 1 -%anagr|0|0|593|0|Anagrafica persone fisiche e giuridiche|100|| +%anagr|0|0|596|0|Anagrafica persone fisiche e giuridiche|100|| diff --git a/ba/f6.trr b/ba/f6.trr index 9ea4a5d77..d1e8bac21 100755 --- a/ba/f6.trr +++ b/ba/f6.trr @@ -1,5 +1,5 @@ 6 -53 +55 TIPOA|1|1|0| CODANAGR|3|5|0| COFI|1|16|0| @@ -53,6 +53,8 @@ NISCRIIDD|1|10|0| UFFCONC|9|3|0| OGGETTI|11|10|0| CAUSQUA|1|2|0| +CATPAR|1|2|0| +ESCPRECOMP|2|1|0| 4 TIPOA+CODANAGR| TIPOA+UPPER(RAGSOC)|X