git-svn-id: svn://10.65.10.50/branches/R_10_00@22757 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1658 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1658 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | ||
| #include <automask.h>
 | ||
| #include <browfile.h>
 | ||
| #include <defmask.h>
 | ||
| #include <dongle.h>
 | ||
| #include <execp.h>
 | ||
| #include <expr.h>
 | ||
| #include <golem.h>
 | ||
| #include <netsock.h>
 | ||
| #include <recarray.h>
 | ||
| #include <relation.h>
 | ||
| #include <sheet.h>
 | ||
| #include <tabmod.h>
 | ||
| #include <tabutil.h>
 | ||
| #include <utility.h>
 | ||
| #include <viswin.h>
 | ||
| 
 | ||
| #include "ba7.h"
 | ||
| #include "ba7100a.h"
 | ||
| #define NOT_TRANS -883
 | ||
| #define NOT_GEST  -884
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TConfig utilities
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| 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 set_ini_var(cfg, para, var, NULL); }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // 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 = get_ini_var(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")); 
 | ||
| 
 | ||
|   _connection = QueryConnection("110", server);
 | ||
|   if (_connection != 0)
 | ||
|   {
 | ||
|     TString buf, req;
 | ||
|     ReadLine(_connection, buf);
 | ||
|     if (buf[0] != '+')
 | ||
|       return error_box(FR("Il server POP3 %s non risponde\nRisultato : %s"),
 | ||
|                        (const char*)server, (const char *)buf);
 | ||
|  
 | ||
|     buf = "USER "; buf << user << "\r\n";
 | ||
|     WriteLine(_connection, buf);
 | ||
|     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);
 | ||
|   bool exec_app(int & err, const TString& appname, TMail_message & msg, TToken_string & sh_row);
 | ||
|   void scan_dir(const TFilename& dir, TMail_messages& box) const;
 | ||
|   bool unattended() const;
 | ||
| 
 | ||
| public:
 | ||
|   void test_delete();
 | ||
|   void fill_messages();
 | ||
|   bool save_sheet_line(int& err, int line = -1);
 | ||
|   void save_all_lines();
 | ||
|   void exec_scripts();
 | ||
|   void auto_save_all();
 | ||
| 
 | ||
|   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");
 | ||
| 				file.fremove();
 | ||
| 				deleted = true;
 | ||
| 			}
 | ||
| 			else
 | ||
| 				if (mailer == "MAPI")
 | ||
| 				{
 | ||
| 					TMail_message* msg = new TMail_message("");
 | ||
| 					msg->set_id(id);
 | ||
| 					mapidel.add(msg);
 | ||
| 					deleted = true;
 | ||
| 				}
 | ||
|     if (deleted)
 | ||
|     {
 | ||
|       _box.destroy(nrow);
 | ||
|       sf.destroy(nrow);
 | ||
|     }
 | ||
|     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();
 | ||
|   }
 | ||
| 
 | ||
|   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_dir(const TFilename& dir, TMail_messages& box) const
 | ||
| {
 | ||
|   TString_array msg;
 | ||
|   TFilename mask = dir;
 | ||
|   mask.add("*.ini");
 | ||
|   ::list_files(mask, msg);
 | ||
| 
 | ||
|   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';
 | ||
| 
 | ||
|       subject.cut(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())
 | ||
|       {
 | ||
|         xvt_fsys_parse_pathname (*row, NULL, NULL, id.get_buffer(), NULL, NULL);
 | ||
| 
 | ||
|         TMail_message* msg = new TMail_message(user(), subject, text, dir);
 | ||
|         msg->set_id(id);
 | ||
| 
 | ||
|         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
 | ||
|           msg->set_date_time(TDate(TODAY));
 | ||
|         
 | ||
|         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();  
 | ||
|   }
 | ||
| 
 | ||
|   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 (int m = 0; m < _box.items(); m++)
 | ||
|   {
 | ||
|     TMail_message& msg = _box.msg(m);
 | ||
|     TToken_string& row = sf.row(m);
 | ||
|     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;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| bool TMailer_mask::exec_app(int& err, const TString& appname, TMail_message& msg, TToken_string & sh_row)
 | ||
| {    
 | ||
|   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();
 | ||
|     {
 | ||
|       ofstream outf(tmp);
 | ||
|       const int items = msg.items();
 | ||
|       bool long_lines = false;
 | ||
|       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 == NOERR;
 | ||
| }
 | ||
| 
 | ||
| bool TMailer_mask::save_sheet_line(int& err, int nrow)
 | ||
| {
 | ||
|   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<6C> <20> 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);
 | ||
|             if (logic == LF_TABCOM)
 | ||
|               subj.insert("%");
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   TFilename appname;
 | ||
|   if (!file2app(subj, appname))  // It hasn't a valid application
 | ||
|   { 
 | ||
|     err = NOT_GEST;
 | ||
|     return false;
 | ||
|   }
 | ||
| 
 | ||
|   TMail_message& full_msg = _box.msg(nrow);
 | ||
|   bool ok = exec_app(err, appname, full_msg, row);
 | ||
|   if (!ok && err == _iskeynotfound)
 | ||
|   {
 | ||
|     TString & first_row = full_msg.row(0);
 | ||
|     int pos = first_row.find("MODIFY");
 | ||
|     if (pos > 0)              
 | ||
|     {
 | ||
|       first_row.overwrite("INSERT", pos);
 | ||
|       ok = exec_app(err, appname, full_msg, row);
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     if (m.is_running())
 | ||
|     {
 | ||
|       m.set(F_CHECKED, "X");
 | ||
|       m.stop_run(K_AUTO_ENTER);
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       row.add("X", 0);
 | ||
|       sf.force_update(nrow);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   // Restore mail recipient
 | ||
| //  if (old_mailto.full())
 | ||
| //    set_ini_var(CONFIG_INSTALL, "Main", "MailTo", old_mailto);
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| 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<6C> <20> 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<67> 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) != 'X') 
 | ||
|   {
 | ||
|     row->get(sf.cid2index(F_BODY), body);
 | ||
|     if (body.find("[Transaction]") < 0) // Scarto i messaggi che non siano transazioni
 | ||
|       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<6C> <20> 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)
 | ||
|   {
 | ||
|     time_t tempo; time(&tempo);
 | ||
|     const struct tm* d = localtime(&tempo);
 | ||
|     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<67> elaborato";
 | ||
|     
 | ||
|     if (mark == 'R')
 | ||
|     {
 | ||
|       msg << "ignorato in quanto ridondante";
 | ||
|       row->add("X", 0); // Marcalo come elaborato comunque
 | ||
|     }
 | ||
| 
 | ||
|     if (mark <= ' ')
 | ||
|     {
 | ||
|       TString body; row->get(sf.cid2index(F_BODY), body);
 | ||
|       if (body.find("[Transaction]") >= 0)
 | ||
|       {
 | ||
|         int err = 0;
 | ||
|         const bool yes = save_sheet_line(err, nrow);
 | ||
|         if (yes)
 | ||
|         {
 | ||
|           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
 | ||
|   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(); 
 | ||
|       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()
 | ||
| {
 | ||
|   if (_mail_semaphore == 0)
 | ||
|   { 
 | ||
|     TSheet_field& sf = sfield(F_MESSAGES);
 | ||
|     test_delete();
 | ||
| 		if (sf.items() == 0)
 | ||
| 			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();             
 | ||
|     }
 | ||
|     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))
 | ||
|     return error_box(FR("Il programma %s <20> gi<67> in esecuzione!"), appname);
 | ||
|   return TSkeleton_application::create();
 | ||
| }
 | ||
| 
 | ||
| void TMailer::main_loop()
 | ||
| {
 | ||
|   WINDOW tray = xvt_trayicon_create(TASK_WIN, 0, appname);
 | ||
| 
 | ||
|   open_files(LF_USER, 0);
 | ||
|   TMailer_mask mm;
 | ||
|   mm.run();
 | ||
| 
 | ||
|   xvt_trayicon_destroy(tray);
 | ||
| }
 | ||
| 
 | ||
| int ba7100(int argc, char* argv[])
 | ||
| {
 | ||
| #if XVT_OS==XVT_OS_WIN32
 | ||
|   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);
 | ||
| #endif
 | ||
|   TMailer app;
 | ||
|   app.run(argc, argv, appname);
 | ||
|   return 0;
 | ||
| }
 |