git-svn-id: svn://10.65.10.50/branches/R_10_00@23050 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1999 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1999 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <agasys.h>
 | ||
| #include <applicat.h>
 | ||
| #include <execp.h>
 | ||
| #include <isamrpc.h>
 | ||
| #include <modaut.h>
 | ||
| #include <prefix.h>
 | ||
| #include <progind.h>
 | ||
| #include <sheet.h>
 | ||
| #include <statbar.h>
 | ||
| #include <urldefid.h>
 | ||
| #include <utility.h>
 | ||
| 
 | ||
| #include "ba1.h"
 | ||
| #include "ba1103.h"
 | ||
| #include "ba1500.h"
 | ||
| #include "ba1600.h"
 | ||
| #include "ba1700a.h"
 | ||
| #include "ba1701.h"
 | ||
| 
 | ||
| // definizioni delle colonne dello sheet
 | ||
| #define C_MODULE 1
 | ||
| #define C_CODE 2
 | ||
| #define C_RELEASE 3
 | ||
| #define C_PATCH 4
 | ||
| #define C_DATAREL 5
 | ||
| #define C_CURRRELEASE 6
 | ||
| #define C_CURRPATCH 7
 | ||
| #define C_CURRDATAREL 8
 | ||
| #define C_ISPATCH 9
 | ||
| #define C_BASEPATCH 10
 | ||
| #define C_OEM 11
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////
 | ||
| //  Metodi di utility
 | ||
| ///////////////////////////////////////////////////////
 | ||
| 
 | ||
| HIDDEN const TString& http_default_path()
 | ||
| { 
 | ||
|   int y,r,t,p;
 | ||
|   main_app().get_version_info(y, r, t, p);
 | ||
|   TString& site = get_tmp_string();
 | ||
|   site.format("http://93.146.247.172/release%02d0/", r);
 | ||
|   return site; 
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| HIDDEN int compare_version(const char* v1, int p1, const char* v2, int p2)
 | ||
| {
 | ||
|   TString16 ver1(v1), ver2(v2);
 | ||
| 
 | ||
|   ver1.trim();
 | ||
|   ver1.ltrim(ver1.len() == 4 ? 2 : 4);
 | ||
|   ver2.trim();
 | ||
|   ver2.ltrim(ver2.len() == 4 ? 2 : 4);
 | ||
|   
 | ||
| 	int res = ver1.compare(ver2, -1, TRUE);
 | ||
|   
 | ||
| 	if (res == 0)
 | ||
| 
 | ||
|     res = p1 - p2;
 | ||
| 
 | ||
|   return res;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN word version2year(const char* v)
 | ||
| {
 | ||
|   TString16 ver(v);
 | ||
|   if (ver.len() == 4)
 | ||
|     ver.insert((v[0] == '9') ? "19" : "20", 0);
 | ||
|   ver.cut(4);
 | ||
|   return atoi(ver);
 | ||
| }
 | ||
| 
 | ||
| static int compare_modules(const TObject** o1, const TObject** o2)
 | ||
| {
 | ||
|   TToken_string& ts1 = *(TToken_string*)(*o1);
 | ||
|   TToken_string& ts2 = *(TToken_string*)(*o2);
 | ||
| 
 | ||
|   int res = 0;
 | ||
|   for (int i = 2; i < 5 && res == 0; i++)
 | ||
|   {
 | ||
|     const TFixed_string s1 = ts1.get(i);
 | ||
|     const TFixed_string s2 = ts2.get(i);
 | ||
|     res = s1.compare(s2, -1, true);
 | ||
|   }
 | ||
|   return res;
 | ||
| }
 | ||
| 
 | ||
| bool is_internet_path(const TString& addr)
 | ||
| {
 | ||
|   if (addr.starts_with("www.", true) || addr.starts_with("http:", true))
 | ||
|     return true;
 | ||
| 
 | ||
|   int a1, a2, a3, a4;
 | ||
|   if (sscanf(addr, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) == 4)
 | ||
|     return true;
 | ||
| 
 | ||
|   return false;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // Maschera principale
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TInstaller_mask : public TArray_sheet
 | ||
| {
 | ||
|   static TInstaller_mask* _curr_mask;
 | ||
|   int _station_type;  //intero che definisce il tipo di installazione (1=std,2=server,3=client)
 | ||
|   bool _installed; // Flag per verificare se almeno un modulo e' stato installato
 | ||
|   bool _setup_run;    //Flag che indica se e' stato lanciato il programma setup.exe
 | ||
|   
 | ||
|   enum { NONE=0, NEW_MENU=1, 
 | ||
|          NEW_MENUPRG=2, NEW_INSTALLER=4, NEW_DLL=8, NEW_SYS=14,
 | ||
|          NEW_TRR=16 };
 | ||
|   int _reboot_program;
 | ||
| 
 | ||
| protected: // TSheet
 | ||
|   virtual bool on_key(KEY key);
 | ||
|   static bool tutti_handler(TMask_field& f, KEY k);
 | ||
|   int get_module_number(const TString& module) const;
 | ||
|   bool should_precheck_module(int modnumber) const;
 | ||
|   bool is_zip_file(const TFilename& n) const;
 | ||
| 
 | ||
|   bool copy_file(const TFilename& src, const TFilename& dst) const;
 | ||
|   bool copy_tree(const char* src_study, const char* dst_study) const;
 | ||
|   int test_station_type() const;
 | ||
| 
 | ||
| protected:
 | ||
|   static bool path_handler(TMask_field& fld, KEY key);
 | ||
|   static bool web_handler(TMask_field& fld, KEY key);
 | ||
|   static bool sheet_notify(TSheet_field& s, int r, KEY k);
 | ||
|   static bool install_handler(TMask_field& fld, KEY key);
 | ||
|   static bool update_handler(TMask_field& f, KEY k);
 | ||
| 
 | ||
|   bool add_module(TConfig& ini, const TString& module, bool patch, int pos = -1);
 | ||
|   bool add_header(TConfig& ini, const TString& module);
 | ||
|   int precheck_modules(bool only_newer = true);
 | ||
|   void update_version();
 | ||
|   void update_disk_and_web_path();
 | ||
|   void kill_files();
 | ||
| 
 | ||
|   int needs_reboot(const TFilename& file) const;
 | ||
|   bool move_file(const TFilename& src, const TFilename& dst) const;
 | ||
|   bool move_module(const TString& module, TInstall_ini& ini, bool update) const;
 | ||
| 
 | ||
|   bool can_install(const char* module, TInstall_ini& ini);
 | ||
|   void install_selection();
 | ||
|   bool install_patches(const TString& module, const TString& lastrelease, int lastpatch , bool onlynew = true);
 | ||
|   KEY askdisk(TString& path, TFilename& cmdline, int d, int dischi, const char* modulo);
 | ||
| 
 | ||
|   bool do_process(TToken_string& commands) const;
 | ||
|   bool pre_process(TInstall_ini& ini, const char* module) const;
 | ||
|   bool post_process(TInstall_ini& ini, const char* module) const;
 | ||
|   bool get_patches_path(TFilename& path) const;
 | ||
|   void parse_internet_path(TString& http_server, TFilename& http_path) const;
 | ||
|   bool is_program_dir(const TFilename& path);
 | ||
|   bool is_visible_patch(TConfig& ini) const;
 | ||
|   bool check_customer() const;
 | ||
| 
 | ||
| public:
 | ||
|   bool installed() const { return _installed;}
 | ||
|   bool setup_run() const { return _setup_run; }
 | ||
|   int station_type() const {return _station_type;} 
 | ||
|   bool autoload();
 | ||
|   bool install(const TString& module, int patch);
 | ||
| 
 | ||
|   void backup() const;
 | ||
|   
 | ||
|   bool run_conversion() const 
 | ||
|   { return installed() && (_reboot_program & NEW_TRR) != 0; } 
 | ||
| 
 | ||
|   TInstaller_mask();
 | ||
|   virtual ~TInstaller_mask();
 | ||
| };
 | ||
| 
 | ||
| TInstaller_mask* TInstaller_mask::_curr_mask = NULL;
 | ||
| 
 | ||
| bool TInstaller_mask::is_visible_patch(TConfig& ini) const
 | ||
| {
 | ||
|   bool yes = true;
 | ||
| 
 | ||
|   TAuto_token_string oem = ini.get("OEM");
 | ||
|   if (oem.full())
 | ||
|   {
 | ||
|     const int my_oem = dongle().oem();
 | ||
|     yes = oem.get_pos(my_oem) >= 0;
 | ||
|     if (!yes) 
 | ||
|     {
 | ||
|       // Stando alla patch non sarei visibile ma devo controllare anche l'install.ini locale
 | ||
|       // in modo da permettere l'aggiunta e la rimozione di nuovi OEM alla lista
 | ||
|       const TString& module = ini.get_paragraph();
 | ||
|       const TString& loc_oem = ini_get_string(CONFIG_GENERAL, module, "OEM");
 | ||
|       if (loc_oem != oem)
 | ||
|         ini_set_string(CONFIG_GENERAL, module, "OEM", oem);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return yes;
 | ||
| }
 | ||
| 
 | ||
| // Copia nello sheet i dati di un modulo prendendoli da un .ini
 | ||
| bool TInstaller_mask::add_module(TConfig& ini, const TString& module, bool patch, int pos)
 | ||
| {
 | ||
|   ini.write_protect();
 | ||
|   if (!ini.set_paragraph(module))
 | ||
|     return false;
 | ||
| 
 | ||
|   // Nasconde i moduli riservati da occhi indiscreti
 | ||
|   if (!is_visible_patch(ini))
 | ||
|     return false;
 | ||
|   
 | ||
|   const int numpatch = ini.get_int("Patch");
 | ||
|   TString4 strpatch; 
 | ||
|   if (numpatch > 0)
 | ||
|     strpatch.format("%04d", numpatch);
 | ||
| 
 | ||
|   TToken_string row;
 | ||
|   row = " ";   // Not selected
 | ||
|   row.add(ini.get("Descrizione"));
 | ||
|   row.add(module);
 | ||
|   row.add(ini.get("Versione"));
 | ||
|   row.add(strpatch);
 | ||
|   row.add(ini.get("Data"));
 | ||
|   row.add(patch ? "X" : " ", C_ISPATCH);
 | ||
|   row.add(ini.get("OEM"), C_OEM);
 | ||
|   
 | ||
|   if (pos < 0)
 | ||
|     add(row);
 | ||
|   else
 | ||
|     insert(row,pos);
 | ||
|   
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| // Copia nello sheet l'intestazione di un modulo prendendola da un .ini
 | ||
| bool TInstaller_mask::add_header(TConfig& ini, const TString& module)
 | ||
| {
 | ||
|   ini.write_protect();
 | ||
|   bool ok = ini.set_paragraph(module);
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     TToken_string row;
 | ||
|     row = " ";   // Not selected
 | ||
|     row.add(ini.get("Descrizione"));
 | ||
|     row.add(ini.get("  "));
 | ||
|     enable_row(add(row),false);
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::should_precheck_module(int modnumber) const
 | ||
| {
 | ||
|   bool ok = modnumber == BAAUT;
 | ||
|   
 | ||
|   if (!ok)
 | ||
|   {
 | ||
|     //se l'installazione <20> un server, prechecka tutti i moduli, a meno che non sia in funzione il server..
 | ||
|     //..di chiavi; in questo caso infatti la chiave <20> unica, ha dunque sicuramente tutti i moduli comuni..
 | ||
|     //..alle varie installazioni client, e quindi basta checkare i moduli sulla chiave come per qualsiasi..
 | ||
|     //..altra installazione
 | ||
|     const TDongle& d = dongle();
 | ||
|     if (station_type() == 2 && d.hardware() != _dongle_network)
 | ||
|     {
 | ||
|       //se sei un server hai tutti i moduli da installare
 | ||
|       ok = d.shown(modnumber);
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       //senno' sei sfigato e ti installa solo i moduli sulla chiave
 | ||
|       ok = d.active(modnumber);
 | ||
|       if (!ok) // Se non hai un modulo ... potresti avere un suo modulo sottinteso
 | ||
|       {
 | ||
|         switch (modnumber)
 | ||
|         {
 | ||
|         case CAAUT: ok = d.active(CMAUT); break; // Se non hai l'analitica ritenta con le commesse
 | ||
|         case TPAUT: ok = d.active(DCAUT); break; // Se non hai Pack ritenta con il CONAI
 | ||
|         default: break;
 | ||
|         }
 | ||
|       } 
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| //che tipo di installazione e'?
 | ||
| int TInstaller_mask::test_station_type() const
 | ||
| {
 | ||
|   TConfig ini(CONFIG_INSTALL, "Main");
 | ||
|   int type = ini.get_int("Type");
 | ||
|   //se type non e' definito nei valori giusti (1=standard,2=server,3=client)
 | ||
|   if (type < 1 || type > 3)
 | ||
|   {
 | ||
|     const bool testdb = ini.get_bool("TestDatabase");
 | ||
|     //const bool testprg = ini.get_bool("TestPrograms");
 | ||
|     if (testdb)
 | ||
|     {
 | ||
|       if (dongle().hardware() == _dongle_network) //se usa un server di chiavi->server
 | ||
|         type = 2;
 | ||
|       else
 | ||
|         type = 1;
 | ||
|     }
 | ||
|     else
 | ||
|       type = 3;
 | ||
| 
 | ||
|     ini.set("Type", type);  //cosi' lo definisce se non c'e'
 | ||
|   }
 | ||
|   return type;
 | ||
| }
 | ||
| 
 | ||
| int TInstaller_mask::precheck_modules(bool only_newer)
 | ||
| {
 | ||
|   TString16 release, currrelease;
 | ||
|   TString4 cod_module;
 | ||
|   int patchlevel, modnumber, currpatch;
 | ||
| 
 | ||
| 	bool check_enabled = true;
 | ||
|   _setup_run = false; //inizializzazione del flag di controllo di lancio di setup.exe
 | ||
| 
 | ||
|   const bool good_customer = check_customer();
 | ||
| 
 | ||
|   TString_array& a = rows_array();
 | ||
|   FOR_EACH_ARRAY_ROW(a, r, row)
 | ||
|   {
 | ||
|     TToken_string& rigar = *row;
 | ||
|     cod_module = rigar.get(C_CODE);
 | ||
|     modnumber = get_module_number(cod_module);
 | ||
|     release = rigar.get(C_RELEASE);
 | ||
|     patchlevel = rigar.get_int(C_PATCH);
 | ||
|     currrelease = rigar.get(C_CURRRELEASE);
 | ||
|     currpatch = rigar.get_int(C_CURRPATCH);
 | ||
|     if (modnumber >= BAAUT && should_precheck_module(modnumber) && 
 | ||
|         release.full() && ((release > currrelease) || 
 | ||
|         (release == currrelease &&  (only_newer ? patchlevel > currpatch : patchlevel >= currpatch) )) 
 | ||
|        )    
 | ||
|     {
 | ||
|       // spunta il modulo o la patch se ho installata la stessa versione
 | ||
|       bool chk = rigar.get_char(C_ISPATCH) != 'X' || release == currrelease;
 | ||
| 
 | ||
|       // non spunta automaticamente il modulo server su installazioni che non siano server
 | ||
|       if (cod_module == "sr" && (test_station_type() != 2 || !xvt_sys_dongle_server_is_running()))
 | ||
|       {
 | ||
|         chk = false;
 | ||
|         disable_row(r);
 | ||
|       }
 | ||
| 
 | ||
|       if (chk && !good_customer && cod_module != "sy")
 | ||
|         chk = false;
 | ||
| 
 | ||
| 			if (check_enabled)
 | ||
|         check(r, chk);
 | ||
| 
 | ||
|       if (chk && only_newer && (cod_module == "sy" || cod_module == "sr")) // se viene checkato il modulo sy (sistema) e/o sr (servers)
 | ||
|       {                                                                    // deve togliere la possibilita' di installare altri moduli.
 | ||
|         for (int i = 0; i < a.items(); i++)
 | ||
|         {
 | ||
|           if (i != r) 
 | ||
|             uncheck(i);     // puo' succedere che il modulo sy o sr non sia il primo
 | ||
| 
 | ||
|           disable_row(i);   // disabilita tutte le righe dello sheet (va fatto DOPO l'uncheck!!!)
 | ||
|         }
 | ||
|         disable(DLG_USER);
 | ||
|         check_enabled = false;  //..ed uscire
 | ||
| 
 | ||
|         if (!run_as_admin())
 | ||
|           warning_box("Per installare il modulo <20> necessario eseguire l'applicazione come amministratore.");
 | ||
|       }
 | ||
|     } //if(modnumber>=0...
 | ||
|   } //FOR_EACH_ARRAY_ROW...
 | ||
|   force_update(); // Indispensabile per vedere le righe aggiornate sullo sheet
 | ||
| 
 | ||
|   enable(F_INSTALL, good_customer);
 | ||
|   if (!good_customer)
 | ||
|   {
 | ||
|     send_campo_xml();
 | ||
| 
 | ||
|     TString html;
 | ||
|     html << "<html><body>"
 | ||
|           << "<h5>Attenzione: chiave " << dongle().number() << " non riconosciuta.</h5>\n" 
 | ||
|           << "<p align=justify>Al fine di poter riattivare la chiave <b>" << dongle().product().before(" ") 
 | ||
|           << "</b> in oggetto e poter quindi effettuare registrazioni, "
 | ||
|           << "La preghiamo di contattare Sirio informatica e sistemi ai seguenti riferimenti:</p><br/>"
 | ||
|           << "<ul><li>Sara Coppini, segreteria commerciale: <br />"
 | ||
|           << "<a href=mailto:scoppini@sirio-is.it>scoppini@sirio-is.it</a> Tel. 348-9897249</li>"
 | ||
|           << "<li>Casella vocale Hotline Campo: <br />"
 | ||
|           << "<a href=mailto:hotlinecampo@sirio-is.it>hotlinecampo@sirio-is.it</a> Tel. 02-36583540</li></ul>"
 | ||
|           << "</body></html>";
 | ||
|     error_box(html);
 | ||
|   }
 | ||
| 
 | ||
|   return items();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| int TInstaller_mask::get_module_number(const TString& module) const
 | ||
| {
 | ||
|   int aut = -1;
 | ||
|   bool ok = false;
 | ||
|   if (module.full())
 | ||
|   {
 | ||
|     if (module == "ba" || module == "sy") //moduli base e sistema: deve ritornare 0;
 | ||
|       return BAAUT;
 | ||
| 
 | ||
|     aut = dongle().module_name2code(module);
 | ||
|     ok = aut < ENDAUT;
 | ||
|   }
 | ||
|   return ok ? aut : -1;
 | ||
| }
 | ||
| 
 | ||
| void TInstaller_mask::update_version()
 | ||
| {
 | ||
|   TInstall_ini ini;
 | ||
| 
 | ||
|   TString_array& a = rows_array();
 | ||
|   FOR_EACH_ARRAY_ROW_BACK(a, m, row)
 | ||
|   {
 | ||
|     if (*row->get(C_CODE) != ' ')
 | ||
|     {
 | ||
|       const TString4 module = row->get(C_CODE);
 | ||
|       ini.set_paragraph(module);
 | ||
| 
 | ||
|       const TString16 newver = row->get(C_RELEASE);
 | ||
|       const TString16 oldver = ini.get("Versione");
 | ||
|       const int numpatch = ini.get_int("Patch");
 | ||
|       TString4 strpatch; 
 | ||
|       if (numpatch > 0) 
 | ||
|         strpatch.format("%04d", numpatch);
 | ||
|       row->add(oldver, C_CURRRELEASE);
 | ||
|       row->add(strpatch, C_CURRPATCH);
 | ||
|       row->add(ini.get("Data"), C_CURRDATAREL);
 | ||
|     }
 | ||
|   }
 | ||
|   force_update();
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::check_customer() const
 | ||
| {
 | ||
|   Tdninst dninst;
 | ||
|   return dninst.check_customer() == 0;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // Cerca nel percorso specificato sulla maschera tutti i possibili files .ini
 | ||
| // utilizzabili per un'installazione e li inserisce nello spreadsheet
 | ||
| bool TInstaller_mask::autoload()
 | ||
| {
 | ||
|   TString_array& mask_rows = rows_array();
 | ||
| 
 | ||
|   TString http_server;
 | ||
|   TFilename http_path, path, ininame;
 | ||
| 
 | ||
|   //controlla se si e' scelto un path di installazione internet o da disco
 | ||
|   const bool internet = get_patches_path(path);
 | ||
|   //se e' un aggiornamento via internet...
 | ||
|   if (internet)
 | ||
|   {
 | ||
|     if (!(xvt_net_get_status() & 0x4)) //la connessione web funziona?...
 | ||
|       return warning_box("Impossibile connettersi al sito con gli aggiornamenti\nVerificare che la connessione Internet sia attiva !");
 | ||
| 
 | ||
|     parse_internet_path(http_server, http_path);  //controlla il path internet scritto nel campo sulla maschera
 | ||
| 
 | ||
|     //se si ritrova dei vecchi file nella directory temporanea, la pulisce per evitare casini
 | ||
|     remove_files(path, true);
 | ||
| 
 | ||
|     ininame = path;
 | ||
|     ininame.add(TInstall_ini::default_name());
 | ||
|     if (!ininame.exist())
 | ||
|     {
 | ||
|       TFilename remote_ini = http_path;
 | ||
| 			remote_ini << TInstall_ini::default_name();
 | ||
| 
 | ||
|       if (remote_ini.full()) // dummy test
 | ||
|       {
 | ||
|         TTimerind contacting(30*1000, TR("Connessione al server HTTP..."), false, false);
 | ||
|         http_get(http_server, remote_ini, ininame);
 | ||
| 
 | ||
|         // Cerca di prelevare anche dninst.zip
 | ||
|         const char* const local_dninst = "setup/dninst.zip";
 | ||
|         TFilename remote_dninst = http_path;
 | ||
|         remote_dninst << local_dninst;
 | ||
|         if (!http_get(http_server, remote_dninst, local_dninst))
 | ||
|         {
 | ||
|           // Se non aggiorno da release riprovo con l'indirizzo dell'OEM
 | ||
|           remote_dninst = http_default_path();
 | ||
|           remote_dninst << local_dninst;
 | ||
|           const int slash = remote_dninst.find('/');
 | ||
|           if (slash > 0)
 | ||
|             http_get(remote_dninst.left(slash), remote_dninst.mid(slash), local_dninst);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   } //if(internet...
 | ||
| 
 | ||
|   if (path.exist())
 | ||
|   {
 | ||
|     ininame = path;
 | ||
|     ininame.add(TInstall_ini::default_name());
 | ||
|   }
 | ||
|   else
 | ||
|     return error_box(TR("Specificare un percorso valido"));
 | ||
| 
 | ||
|   TWait_cursor hourglass;
 | ||
|   destroy();
 | ||
|   force_update();
 | ||
| 
 | ||
|   TString_array modules;
 | ||
| 
 | ||
|   //cerca sull'install.ini di origine se lo trova (ininame e' il path dell'install.ini remoto)
 | ||
|   if (ininame.exist())
 | ||
|   {
 | ||
|     // Presente il file ini generale "install.ini" (moduli;immagine cd)
 | ||
|     TInstall_ini ini(ininame);
 | ||
|     ini.list_paragraphs(modules); //riempie modules con la lista dei paragrafi sul .ini ***
 | ||
| 
 | ||
|     FOR_EACH_ARRAY_ROW(modules, i, row)
 | ||
|     {
 | ||
|       const TString& module = *row;
 | ||
|       if (module[0] == '_' || module.len() == 2)
 | ||
|       {
 | ||
|         if (module[0] == '_')
 | ||
|           add_header(ini, module);
 | ||
|         else
 | ||
|         {
 | ||
|           TFilename mod_ini = ininame.path();
 | ||
|           mod_ini.add(module);
 | ||
|           mod_ini << "inst.ini";
 | ||
|           //controlla se esiste il pacco zippato del modulo attraverso l'esistenza del file..
 | ||
| 					//..XXinst.ini
 | ||
|           if (mod_ini.exist())
 | ||
|           {
 | ||
|             TInstall_ini moduleini(mod_ini);
 | ||
|             add_module(moduleini, module, false);
 | ||
|           }
 | ||
|           else
 | ||
|             add_module(ini, module, false);
 | ||
|         }
 | ||
|       } //if(module[0]...
 | ||
|     } //FOR_EACH_ARRAY_ROW(...
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     // Presenti i singoli file .ini dei moduli (pacchi ma non patches!)
 | ||
|     ininame = path;
 | ||
|     ininame.add("??inst.ini");
 | ||
|     list_files(ininame, modules); //ritorna la lista dei files presenti nel .ini della patch ***
 | ||
|     FOR_EACH_ARRAY_ROW(modules, m, row)
 | ||
|     {
 | ||
|       TString& ininame = *row;
 | ||
|       ininame.lower();
 | ||
|       const int pos = ininame.find("inst.ini");
 | ||
|       CHECKS(pos >= 2, "Invalid installation configuration: ", (const char*)ininame);
 | ||
|       const TString4 module = ininame.mid(pos-2, 2);
 | ||
|       TConfig ini(ininame, module);
 | ||
|       add_module(ini, module, false);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   modules.destroy();
 | ||
| 
 | ||
|   if (internet) //internet patches
 | ||
|   {
 | ||
|     TProgress_monitor pi(1, TR("Controllo lista aggiornamenti"), false); // progind NON bloccabile: causa errore impossibile!
 | ||
|     http_dir(http_server, http_path, modules);
 | ||
|     pi.set_max(modules.items());
 | ||
|     pi.set_text(TR("Download lista aggiornamenti"));
 | ||
|     for (int i = modules.last(); i >= 0; i--)
 | ||
|     {
 | ||
|       if (!pi.add_status())
 | ||
|         break;
 | ||
|       TString& str = modules.row(i);
 | ||
|       if (str.ends_with("a.ini", true))
 | ||
|       {
 | ||
|         /* Triste nescessita': si rischia di non caricare nessuna patch
 | ||
|         const TString& module = str.left(2);
 | ||
|         const int patch = atoi(str.mid(2, 4));
 | ||
|         const int mypatch = ini_get_int(CONFIG_GENERAL, module, "Patch");
 | ||
|         if (patch > 0 && patch < mypatch) 
 | ||
|         {
 | ||
|           modules.destroy(i);
 | ||
|           continue; // Non fare il download delle patch inutili
 | ||
|         }
 | ||
|         */
 | ||
| 
 | ||
|         TFilename remote = http_path;
 | ||
|         remote << str;
 | ||
| 
 | ||
|         ininame = path;
 | ||
|         ininame.add(str);
 | ||
| 
 | ||
|         if (!ininame.exist() && !http_get(http_server, remote, ininame))
 | ||
|         {
 | ||
|           error_box(FR("Errore di trasferimento del file %s"), (const char*)remote);
 | ||
|           modules.destroy(i);
 | ||
|         }
 | ||
|         str = ininame;
 | ||
|       }
 | ||
|       else
 | ||
|         modules.destroy(i);
 | ||
|     }
 | ||
|     modules.pack();
 | ||
|   }
 | ||
|   else  //normal patches
 | ||
|   {
 | ||
|     ininame = path;
 | ||
|     ininame.add("??????a.ini");
 | ||
|     list_files(ininame, modules); 
 | ||
|   }
 | ||
| 
 | ||
|   if (modules.items() > 0)  //ordina i moduli come sull'install.ini locale (per avere SY come primo
 | ||
|   {                         //modulo e via via gli altri)
 | ||
|     TInstall_ini installini;
 | ||
|     TString_array paragrafi;
 | ||
|     TFilename file;
 | ||
| 
 | ||
|     installini.list_paragraphs(paragrafi);
 | ||
| 		// rimozione del produttore sull'install.ini locale ora obsoleto..
 | ||
|   	installini.remove("Producer");
 | ||
| 
 | ||
|     FOR_EACH_ARRAY_ROW(modules, am, arow)
 | ||
|     {
 | ||
|       file = *arow;
 | ||
|       file = file.name();
 | ||
|       int pos = paragrafi.find(file.left(2));
 | ||
|       if (pos <= 0)
 | ||
|         pos = 10000+am;
 | ||
|       TString8 str;
 | ||
|       str.format("%05d", pos);  //aggiunge un numero d'ordine sulla sinistra del nome del file..
 | ||
|       arow->insert(str);
 | ||
|     }
 | ||
|     modules.sort(); //..cosi' che la sort (che ordina alfabeticamente) sistemi la lista moduli
 | ||
| 
 | ||
|     FOR_EACH_ARRAY_ROW(modules, bm, brow) //rimette i nomi dei moduli a posto (toglie il numero d'ordine)
 | ||
|       brow->ltrim(5);
 | ||
|   }
 | ||
| //genera le righe dello sheet di installazione
 | ||
|   FOR_EACH_ARRAY_ROW(modules, am, arow)
 | ||
|   {
 | ||
|     TString& ininame = *arow;
 | ||
|     ininame.lower();
 | ||
|     if (fsize(ininame) < 8)
 | ||
|     {
 | ||
|       xvt_fsys_remove_file(ininame);
 | ||
|       continue;
 | ||
|     }
 | ||
|     const int pos = ininame.find("a.ini");
 | ||
|     CHECKS(pos >= 6, TR("Configurazione di installazione non valida: "), (const char*)ininame);
 | ||
|     const TString4 module = ininame.mid(pos-6, 2);
 | ||
|     TConfig ini(ininame, module); 
 | ||
|     ini.write_protect();
 | ||
|     int r;
 | ||
|     for (r = int(items()-1); r >= 0; r--)
 | ||
|     {
 | ||
|       if (module == row(r).get(C_CODE))
 | ||
|         break;
 | ||
|     }
 | ||
| 
 | ||
|     if (r >= 0)
 | ||
|     {
 | ||
|       if (is_visible_patch(ini))
 | ||
|       {
 | ||
|         const TString16 patchversion = ini.get("Versione");
 | ||
|         const int patchlevel = ini.get_int("Patch");
 | ||
|         TToken_string& row = mask_rows.row(r);
 | ||
| 			  const TString16 release(row.get(C_RELEASE));
 | ||
|         if (patchversion.mid(4) == release.mid(4) && // se le versioni corrispondono ...
 | ||
|             patchlevel > row.get_int(C_PATCH))       // ..e il patchlevel <20> superiore
 | ||
|         {   
 | ||
|           TString4 patch; patch.format("%04d", patchlevel);  //aggiunge zeri per avere 3 cifre sempre
 | ||
|           row.add(patch, C_PATCH); // aggiorna il patchlevel mostrato per il modulo
 | ||
|           row.add(ini.get("Data"), C_DATAREL); // aggiorna data di rilascio
 | ||
|           if (row.get_char(C_ISPATCH)<=' ') // se era un modulo ...
 | ||
|           {
 | ||
|             row.add("+", C_ISPATCH); // .....setta la presenza di patches
 | ||
|             row.add(row.get(C_PATCH), C_BASEPATCH); // memorizza patch del modulo
 | ||
|           }
 | ||
| 				  if (release < patchversion)
 | ||
| 					  row.add(patchversion, C_RELEASE);
 | ||
|           row.add(ini.get("OEM"), C_OEM);
 | ||
|         }
 | ||
|       }
 | ||
|       else
 | ||
|         destroy(r); // Elimina patch di altri OEM erroneamente inserite
 | ||
|     } 
 | ||
|     else
 | ||
|       add_module(ini, module, true);
 | ||
|   }
 | ||
|   update_version();
 | ||
|   const bool ok = precheck_modules() > 0;
 | ||
| 
 | ||
|   if (!ok)
 | ||
|     error_box(FR("Non e' stato trovato nessun modulo da installare\nin %s"), (const char*)path);
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::do_process(TToken_string& commands) const
 | ||
| {
 | ||
|   bool ok = true;
 | ||
|   TFilename cmd;
 | ||
|   for (const char* c = commands.get(0); c && ok; c = commands.get())
 | ||
|   {
 | ||
|     cmd = c;
 | ||
|     if (cmd.full())
 | ||
|     {
 | ||
|       TWait_cursor hourglass;
 | ||
|       TExternal_app app(cmd);
 | ||
|       ok = app.run(false,3,true) == 0;
 | ||
|     }
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::pre_process(TInstall_ini& ini, const char* module) const
 | ||
| {
 | ||
|   TAuto_token_string commands(ini.get("PreProcess", module));
 | ||
|   bool ok = do_process(commands);
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::post_process(TInstall_ini& ini, const char* module) const
 | ||
| {
 | ||
|   TAuto_token_string commands(ini.get("PostProcess", module));
 | ||
|   return do_process(commands);
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::can_install(const char* module, TInstall_ini& ini)
 | ||
| {
 | ||
|   ini.set_paragraph(module);
 | ||
|   if (!is_visible_patch(ini))
 | ||
|     return false;
 | ||
| 
 | ||
|   const TString& version = ini.version(module);
 | ||
|   const word year = version2year(version);
 | ||
|   if (year < 2091)
 | ||
|     return error_box(FR("Il modulo '%s' non ha una versione valida."), module);
 | ||
| 
 | ||
|   if (!dongle().demo() && year > dongle().year_assist())  //devo aggiornare l'anno di assistenza?
 | ||
|   {
 | ||
|     if (!update_assistance_year())  //sono riuscito ad aggiornare l'anno di assistenza?
 | ||
|       return false;
 | ||
|   }
 | ||
| 
 | ||
|   TAuto_token_string altri(ini.get("Moduli", module));
 | ||
|   if (xvt_str_compare_ignoring_case(module, "sy") != 0) //SY e' indipendente dagli altri moduli
 | ||
|   {
 | ||
|     if (xvt_str_compare_ignoring_case(module, "ba") != 0 && altri.get_pos("ba") < 0)
 | ||
|       altri.add("ba");
 | ||
|   }
 | ||
| 
 | ||
|   bool ok = true;
 | ||
|   TString submodule;
 | ||
|   TInstall_ini curini;
 | ||
|   for (const char* mod = altri.get(0); mod && ok; mod = altri.get())
 | ||
|   {
 | ||
|     submodule = mod;
 | ||
|     if (submodule.len() == 2)
 | ||
|     {
 | ||
|       if (curini.get("Versione", submodule).empty())
 | ||
|       {
 | ||
|         TString msg;
 | ||
|         msg.format(FR("L'installazione del modulo %s richiede la presenza del modulo %s."), 
 | ||
|                    (const char*)module, (const char*)submodule);
 | ||
|         msg << '\n' << TR("Si desidera procedere alla sua installazione?");
 | ||
|         ok = yesno_box(msg);
 | ||
|         if (ok)
 | ||
|           ok = install(submodule, 0);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| int TInstaller_mask::needs_reboot(const TFilename& file) const
 | ||
| { 
 | ||
|   char fname[_MAX_FNAME], ext[_MAX_EXT];
 | ||
|   xvt_fsys_parse_pathname(file, NULL, NULL, fname, ext, NULL);
 | ||
| 
 | ||
|   int underscore = NONE;
 | ||
|   if (xvt_str_compare_ignoring_case(ext, "exe") == 0)
 | ||
|   {
 | ||
|     if (xvt_str_compare_ignoring_case(fname, "ba0") == 0)
 | ||
|       underscore = NEW_MENUPRG; else
 | ||
|     if (xvt_str_compare_ignoring_case(fname, "ba1") == 0)
 | ||
|       underscore = NEW_INSTALLER;
 | ||
|   } else
 | ||
|   if (xvt_str_compare_ignoring_case(ext, "dll") == 0)
 | ||
|     underscore = NEW_DLL; else
 | ||
|   if (xvt_str_compare_ignoring_case(ext, "men") == 0)
 | ||
|     underscore = NEW_MENU; else
 | ||
|   if (xvt_str_compare_ignoring_case(ext, "trr") == 0 || xvt_str_compare_ignoring_case(ext, "dir") == 0)
 | ||
|     underscore = NEW_TRR;
 | ||
|   return underscore;
 | ||
| }
 | ||
| 
 | ||
| // Controlla se un file puo' essere scompattato.
 | ||
| // Attenzione: dninst.zip e' un falso zip
 | ||
| bool TInstaller_mask::is_zip_file(const TFilename& n) const
 | ||
| {
 | ||
| 	bool yes = xvt_str_compare_ignoring_case(n.ext(), "zip") == 0 && 
 | ||
| 		         xvt_str_compare_ignoring_case(n.name_only(), "dninst") != 0;
 | ||
|   return yes;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::copy_file(const TFilename& src, const TFilename& dst) const
 | ||
| {
 | ||
|   // Crea la cartella di destinazione se necessario
 | ||
|   const char* dstdir = dst.path();
 | ||
|   if (*dstdir && !xvt_fsys_mkdir(dstdir))
 | ||
|     return error_box(FR("Impossibile creare la cartella %s"), dst.path());
 | ||
| 
 | ||
|   // Copia veramente il file
 | ||
|   return ::fcopy(src, dst);
 | ||
| }
 | ||
| 
 | ||
| // sposta il file dal direttorio temporaneo a quello passato come destinazione
 | ||
| bool TInstaller_mask::move_file(const TFilename& src, const TFilename& dst) const
 | ||
| {
 | ||
|   TFilename dest = dst;
 | ||
|   const int reboot = needs_reboot(dest);
 | ||
|   if ((reboot & NEW_SYS)!=0 && dst.exist())
 | ||
|   {
 | ||
|     dest.rtrim(1);
 | ||
|     dest << '_';
 | ||
|   }
 | ||
| 
 | ||
|   const bool is_zip = is_zip_file(src);
 | ||
|   const long filesize = fsize(src) * (is_zip ? 4 : 1);
 | ||
| 
 | ||
|   if (xvt_fsys_test_disk_free_space(dest.path(), filesize) == 0)
 | ||
|     return error_box(TR("Lo spazio disponibile e' insufficiente!"));
 | ||
| 
 | ||
|   const bool write_ok = copy_file(src, dest);
 | ||
|   if (write_ok && is_zip)
 | ||
|     aga_unzip(src, dest.path());
 | ||
|     
 | ||
|   if (write_ok)
 | ||
|     src.fremove();
 | ||
| 
 | ||
|   if (write_ok)
 | ||
|   {
 | ||
|     (int&)_reboot_program |= reboot; // Skip const!
 | ||
|   }
 | ||
|   return write_ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::move_module(const TString& module, TInstall_ini& ini, bool update) const
 | ||
| {
 | ||
|   bool ok = true;
 | ||
| 
 | ||
|   TFilename tempdir; tempdir.tempdir();
 | ||
|   const TString& destdir = get(F_CURPATH);
 | ||
| 
 | ||
|   TString_array list;
 | ||
|   ini.build_list(module, list);
 | ||
|   FOR_EACH_ARRAY_ROW(list, f, file)
 | ||
|   {
 | ||
|     TFilename src = tempdir;
 | ||
|     src.add(file->get(0));
 | ||
|     if (update)
 | ||
|     {
 | ||
|       TFilename dst = destdir;
 | ||
|       dst.add(file->get(0));
 | ||
|       const bool move_ok = move_file(src, dst);
 | ||
|       if (!move_ok)
 | ||
|         ok = update = false;
 | ||
|     }
 | ||
|     if (!update)
 | ||
|       src.fremove();
 | ||
|   }
 | ||
|   
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::copy_tree(const char* src_study, const char* dst_study) const
 | ||
| {
 | ||
|   xvt_fsys_save_dir();
 | ||
|   TFilename mask(src_study); mask.add("*.");
 | ||
|   SLIST dlist = xvt_fsys_list_files(DIR_TYPE, mask, TRUE);
 | ||
|   xvt_fsys_restore_dir();
 | ||
|   TProgress_monitor pd(xvt_slist_count(dlist), TR("Copia cartelle"));
 | ||
| 
 | ||
|   TString msg; // Messaggio di progresso
 | ||
| 
 | ||
|   bool go_on = true;
 | ||
|   for (SLIST_ELT d = xvt_slist_get_first(dlist); d && go_on; d = xvt_slist_get_next(dlist, d))
 | ||
|   { 
 | ||
|     if (!pd.add_status())
 | ||
|     {
 | ||
|       go_on = false;
 | ||
|       break;
 | ||
|     }
 | ||
| 
 | ||
|     const TFilename dir = xvt_slist_get(dlist, d, NULL);
 | ||
|     
 | ||
|     TString name = dir.name(); name.lower();
 | ||
|     if (name == "cesp") // Ignora la vetusta cartella Cespiti in FoxPro
 | ||
|       continue;
 | ||
| 
 | ||
|     msg.cut(0) << TR("Copia di ") << name;
 | ||
|     pd.set_text(msg);
 | ||
|  
 | ||
|     mask = dir; mask.add("*.*");
 | ||
|     TString_array files; list_files(mask, files);
 | ||
| 
 | ||
|     TProgress_monitor pi(files.items(), TR("Copia file"));
 | ||
| 
 | ||
|     TFilename dst;
 | ||
|     FOR_EACH_ARRAY_ROW(files, i, f)
 | ||
|     {
 | ||
|       if (!pi.add_status())
 | ||
|       {
 | ||
|         go_on = false;
 | ||
|         break;
 | ||
|       }
 | ||
|       TFilename src(*f);
 | ||
|       TString16 ext(src.ext()); ext.lower();
 | ||
|       if (ext != "zip" && ext != "rar" && ext != "mdb" && ext != "inf") 
 | ||
|       {
 | ||
|         msg.cut(0) << TR("Copia di ") << src;
 | ||
|         pi.set_text(msg);
 | ||
| 
 | ||
|         dst = dst_study;
 | ||
|         dst.add(name);
 | ||
|         dst.add(src.name());
 | ||
|         copy_file(src, dst);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   xvt_slist_destroy(dlist);
 | ||
| 
 | ||
|   return go_on;
 | ||
| }
 | ||
| 	
 | ||
| void TInstaller_mask::backup() const
 | ||
| { 
 | ||
|   TFilename src = firm2dir(-1);
 | ||
|   if (!isalnum(src.right(1)[0]))
 | ||
|     src.rtrim(1);
 | ||
|   TFilename dst(src); 
 | ||
|   dst << ' ' << TDate(TODAY).date2ansi(); // Lo spazio rende inutilizzabile lo studio
 | ||
| 
 | ||
|   TToken_string msg(256, '\n');
 | ||
|   msg.add(TR("Si consiglia creare una copia dello studio ")); msg << src.name(); 
 | ||
|   msg.add(TR("nella cartella ")); msg << dst; 
 | ||
|   msg.add(TR("L'operazione potrebbe richiedere alcuni minuti."));
 | ||
|   msg.add("");
 | ||
|   msg.add(TR("Si desidera effetture la copia?"));
 | ||
|   if (yesno_box(msg))
 | ||
|     copy_tree(src, dst);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| KEY TInstaller_mask::askdisk(TString & path, TFilename & cmdline, int d, int dischi, const char * modulo)
 | ||
| {
 | ||
|   TMask retry_mask(TR("Inserimento disco"),1,80,10);
 | ||
| 
 | ||
|   retry_mask.add_static((F_PATH==101 ? 102:101),0,
 | ||
|     format(FR("Inserire il disco %d di %d del modulo '%s' nell'unit<69>"), d, dischi, modulo)
 | ||
|       ,2,2);
 | ||
|   retry_mask.add_static(F_PATH+3,0,TR("oppure indicare un percorso diverso"),2,3);
 | ||
| 
 | ||
|   retry_mask.add_string(F_PATH,0,"",2,5,48);
 | ||
|   retry_mask.add_button(DLG_OK,0,TR("Riprova"),-12,7,9,2);
 | ||
|   retry_mask.add_button(DLG_QUIT,0,"",-22,7,9,2);
 | ||
|   retry_mask.set(F_PATH,path);
 | ||
|   KEY k;
 | ||
|   do {
 | ||
|     if ((k=retry_mask.run())==K_QUIT )
 | ||
|       break;
 | ||
|     if (!retry_mask.get(F_PATH).blank())
 | ||
|     {
 | ||
|       if (fexist(retry_mask.get(F_PATH)))
 | ||
|       {
 | ||
|         TString16 tmpname(cmdline.name() );
 | ||
|         cmdline= path = retry_mask.get(F_PATH);
 | ||
|         cmdline.add(tmpname);
 | ||
|         break;
 | ||
|       }
 | ||
|       else
 | ||
|         error_box(TR("Il percorso indicato non e' valido"));
 | ||
|     }
 | ||
|   } while (true);
 | ||
|   return k;
 | ||
| }
 | ||
| 
 | ||
| //rimozione da disco dei files da eliminare indicati nei paragrafi kill..
 | ||
| //..e successivo aggiornamento dell'install.ini in modo da non avere pi<70> tra i piedi i files killati
 | ||
| void TInstaller_mask::kill_files()
 | ||
| {
 | ||
|   //apre l'install.ini locale per effettuare l'aggiornamento
 | ||
|   TInstall_ini ini;
 | ||
|   //giro su tutti i sottomoduli di tipo 99 con l'elenco dei files da uccidere
 | ||
|   TString_array paragraph_names;
 | ||
|   ini.list_paragraphs(paragraph_names);
 | ||
| 
 | ||
|   FOR_EACH_ARRAY_ROW(paragraph_names, nriga, riga)
 | ||
|   {
 | ||
|     //interessano solo i paragrafi con le killer list
 | ||
|     if (riga->ends_with("99") && ini.set_paragraph(*riga))
 | ||
|     { 
 | ||
|       TString_array killed;
 | ||
| 
 | ||
|       TToken_string rigaini;
 | ||
|       TFilename filetokill;
 | ||
|       for (int k = 0;; k++)
 | ||
|       {
 | ||
|         rigaini = ini.get("Kill", NULL, k, "");
 | ||
|         if (rigaini.empty())
 | ||
|           break;
 | ||
|         filetokill = rigaini.get(0);
 | ||
|         if (filetokill.find('*') >= 0 || filetokill.find('?') >= 0)
 | ||
|         {
 | ||
|           TString_array filelist;
 | ||
|           list_files (filetokill, filelist);
 | ||
|           FOR_EACH_ARRAY_ROW(filelist, r, file)
 | ||
|           {
 | ||
|             filetokill = *file;
 | ||
|             if (filetokill.exist()) 
 | ||
|               filetokill.fremove();
 | ||
|             killed.add(filetokill);
 | ||
|           }
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           if (filetokill.exist()) 
 | ||
|             filetokill.fremove();
 | ||
|           killed.add(filetokill);
 | ||
|         }
 | ||
|       } //for(int k=0...
 | ||
| 
 | ||
|       for (int s = 0; s <= 9 && !killed.empty(); s++)
 | ||
|       {
 | ||
|         const TString4 mod = riga->left(2);
 | ||
|         const int cicli = mod == "ba" ? 2 : 1;
 | ||
|         for (int c = 1; c <= cicli; c++)
 | ||
|         {
 | ||
|           TString4 module = c == 1 ? mod : "sy";
 | ||
|           module << s;
 | ||
|           TAssoc_array& vars = ini.list_variables(module);
 | ||
|           FOR_EACH_ASSOC_STRING(vars, hobj, key, str)
 | ||
|           {
 | ||
|             const int idx = killed.find(str);
 | ||
|             if (idx >= 0)
 | ||
|             {
 | ||
|               ini.remove(key);
 | ||
|               killed.destroy(idx, true);
 | ||
|             }
 | ||
|           }
 | ||
|         }
 | ||
|       } //for (int s...
 | ||
|     } //if (riga->ends_with...
 | ||
|   } //FOR_EACH_ARRAY_ROW(...
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::install(const TString& module, int patchlevel)
 | ||
| {
 | ||
|   bool cancelled = false;
 | ||
|   bool ok = false;
 | ||
|   TString msg;              // stringa per i messaggi
 | ||
|   TString16 lastrelease;    // release che sto installando
 | ||
|   int lastpatch = patchlevel; // patchlevel che sto installando
 | ||
| 
 | ||
|   TFilename path ;
 | ||
|   TString http_server;
 | ||
|   TFilename http_path;
 | ||
|   
 | ||
|   const bool internet = get_patches_path(path);
 | ||
|   if (internet)
 | ||
|     parse_internet_path(http_server,http_path );
 | ||
| 
 | ||
|   const bool is_a_patch = (patchlevel > 0);
 | ||
|   //file .ini con le info di installazione (es. bainst.ini o ba0883.ini)
 | ||
|   TFilename remote_ininame = path;
 | ||
|   remote_ininame.add(module);
 | ||
| 
 | ||
|   //completa il nome del file .ini controllando se <20> una patch (es. ba0883a.ini) o se <20> un pacco (es. bainst.ini)
 | ||
|   if (is_a_patch)
 | ||
|   {
 | ||
|     TString16 name;
 | ||
|     name.format("%04da.ini", patchlevel);
 | ||
|     remote_ininame << name;
 | ||
|   }
 | ||
|   else
 | ||
|     remote_ininame << "inst.ini";
 | ||
| 
 | ||
|   if (internet && !remote_ininame.exist())
 | ||
|   {
 | ||
|     TFilename remote = remote_ininame.name();
 | ||
|     remote.insert(http_path, 0);
 | ||
|     http_get(http_server, remote, remote_ininame);
 | ||
|   }
 | ||
| 
 | ||
|   if (remote_ininame.exist())
 | ||
|   {
 | ||
|     // esiste un particolare .ini con formato XXinst.ini (moduli) o con XX9999a.ini (patch)
 | ||
|     //----------------------------------------------
 | ||
|     // (INSTALLAZIONE DA DIRECTORY CON FILES .ZIP)
 | ||
|     //----------------------------------------------
 | ||
|     //remote_ini <20> il file .ini con le info di installazione (es. ba0883a.ini, bainst.ini)
 | ||
|     TInstall_ini* remote_ini = new TInstall_ini(remote_ininame);
 | ||
|     remote_ini->write_protect();
 | ||
|     lastpatch = remote_ini->get_int("Patch", module);
 | ||
|     lastrelease = remote_ini->get("Versione", module);
 | ||
| 
 | ||
|     //se non pu<70> installare il modulo chiude il remote_ini
 | ||
|     if (!can_install(module, *remote_ini))
 | ||
|     {
 | ||
|       delete remote_ini;
 | ||
|       return false;
 | ||
|     }
 | ||
| 
 | ||
|     //antico controllo del numero di dischetti (ora sempre = 1)
 | ||
|     const int dischi = remote_ini->get_int("Dischi", module);
 | ||
|     ok = dischi > 0;
 | ||
|     if (!ok)
 | ||
|       return error_box(FR("Impossibile determinare il numero dei dischetti in %s"), remote_ininame.name());
 | ||
|     else
 | ||
|     {
 | ||
|       if (patchlevel == 0)
 | ||
|         ok = pre_process(*remote_ini, module);
 | ||
|       if (!ok)
 | ||
|       {
 | ||
|         delete remote_ini;
 | ||
|         return false;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     // DECOMPRESSIONE
 | ||
|     // ----------------   
 | ||
|     // viene decompresso il file .zip collegato al file remote_ini (es. ba0883a1.zip, bainst.zip)
 | ||
| 
 | ||
|     TProgind* pi = NULL;
 | ||
|     if (dischi > 1)
 | ||
|     {
 | ||
|       msg = TR("Decompressione");
 | ||
|       if (is_a_patch)
 | ||
|         msg << TR(" della patch ") << patchlevel ;
 | ||
|       msg << TR(" del modulo '") << module << TR("' in corso...");
 | ||
|       pi = new TProgind(dischi, msg, false, true);
 | ||
|     }
 | ||
| 
 | ||
|     TFilename tempdir; 
 | ||
|     tempdir.tempdir();
 | ||
|     
 | ||
| 		// File tottale dei vari sotto-zip
 | ||
| 		TFilename totti = tempdir; 
 | ||
|     totti.add(module); 
 | ||
|     totti.ext("zip");
 | ||
|     
 | ||
|     //si costruisce il nome dello zip
 | ||
|     for (int d = 1; d <= dischi && ok; d++)
 | ||
|     {
 | ||
|       TFilename chunk = path;
 | ||
|       chunk.add(module);
 | ||
|       if (patchlevel > 0)
 | ||
|       {
 | ||
|         TString8 name;
 | ||
|         name.format("%04da", patchlevel);
 | ||
|         chunk << name;
 | ||
|       }
 | ||
|       else
 | ||
|         chunk << "inst";
 | ||
|       chunk << d << ".zip";
 | ||
| 
 | ||
|       if (internet && !chunk.exist())
 | ||
|       {
 | ||
|         TFilename remote = chunk.name();
 | ||
|         remote.insert(http_path, 0);
 | ||
|         if (!http_get(http_server, remote, chunk))
 | ||
|           error_box(FR("Errore di trasferimento del file '%s'"), (const char*)remote);
 | ||
|       }
 | ||
| 
 | ||
|       //antichi controlli in caso di multidischetto
 | ||
|       ok = chunk.exist();
 | ||
|       if (!ok && !internet)  // Chiedi cambio disco (solo se non sta scaricando da internet)
 | ||
|       {
 | ||
|         while (!ok)
 | ||
|         {
 | ||
|           if (askdisk(path, chunk, d, dischi, (const char*)remote_ini->get("Descrizione")) == K_QUIT)
 | ||
|             break;
 | ||
|           ok = chunk.exist();
 | ||
|           if (!ok)
 | ||
|             message_box(FR("Impossibile trovare il file '%s'"), (const char*)chunk);
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       if (ok)
 | ||
|       {
 | ||
|         const long required = fsize(chunk) * (dischi - d + 1) * 4;
 | ||
|         if (!xvt_fsys_test_disk_free_space(tempdir, required))        
 | ||
|         {
 | ||
|           ok = yesno_box(TR("Lo spazio su disco potrebbe essere insufficiente:\nSi desidera continuare ugualmente?"));
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       if (ok)
 | ||
|         ::fcopy(chunk, totti, d > 1);  // Somma il chunk al totale
 | ||
|     }
 | ||
|     if (pi != NULL)
 | ||
|     {
 | ||
|       delete pi;
 | ||
|       pi = NULL;
 | ||
|     }
 | ||
| 
 | ||
|     //scompattamento vero e proprio dello zip
 | ||
|   	aga_unzip(totti, tempdir); // Scompatta il file totale zip
 | ||
| 		totti.fremove();                // Elimina il file totale zip
 | ||
| 
 | ||
| 
 | ||
|     // TRASFERIMENTO
 | ||
|     // -----------------
 | ||
|     if (ok)
 | ||
|     {
 | ||
|       // si assicura che sia leggibile il .ini del primo disco
 | ||
|       do 
 | ||
| 			{
 | ||
|         TFilename cmdline = path;
 | ||
|         cmdline.add(remote_ininame.name());
 | ||
|         ok = cmdline.exist();
 | ||
|         if (!ok)
 | ||
|         {
 | ||
|           if (askdisk(path, cmdline, 1, dischi, (const char*)remote_ini->get("Descrizione")) == K_QUIT)
 | ||
|            break;
 | ||
|           ok = fexist(cmdline);
 | ||
|           if (!ok)
 | ||
|             message_box(FR("Impossibile trovare %s\n"), (const char*)cmdline);
 | ||
|           else
 | ||
|           {
 | ||
|             delete remote_ini;
 | ||
|             remote_ini = new TInstall_ini (cmdline);
 | ||
|           }
 | ||
|         }
 | ||
|       } while (!ok);
 | ||
| 
 | ||
|       if (ok)
 | ||
|       {
 | ||
|         TWait_cursor hourglass;
 | ||
|         msg.cut(0);
 | ||
|         msg << TR("Aggiornamento del modulo '") << module << TR("' in corso...");
 | ||
|         xvtil_statbar_set(msg);
 | ||
|         ok = move_module(module, *remote_ini, true);
 | ||
| 
 | ||
|         if (ok)
 | ||
|         {
 | ||
|           TAuto_token_string altri(remote_ini->get("Moduli", module));
 | ||
|           FOR_EACH_TOKEN(altri, mod)
 | ||
|           {
 | ||
|             const TString16 submod = mod;
 | ||
|             if (submod.len() > 2) // sposta sottomoduli esterni
 | ||
|             {
 | ||
|               bool upd = ok;
 | ||
|               if (ok)
 | ||
|               {
 | ||
|                 TInstall_ini local_cur_ini;
 | ||
|                 const TString16 curver = local_cur_ini.version(submod);
 | ||
|                 const int curpatch = local_cur_ini.patch(submod);
 | ||
|                 const TString16 reqver = remote_ini->version(submod);
 | ||
|                 const int reqpatch = remote_ini->patch(submod);
 | ||
|   
 | ||
|                 int distance = compare_version(reqver, reqpatch, curver, curpatch);
 | ||
|                 upd = distance > 0;
 | ||
|               }
 | ||
|               ok &= move_module(submod, *remote_ini, upd);
 | ||
|               if (upd && ok)  // marca sull'install.ini di destinazione l'avvenuta installazione del sottomodulo "esterno"
 | ||
|                 remote_ini->export_paragraph(submod, TInstall_ini::default_name(), !is_a_patch);
 | ||
|             }
 | ||
|           }
 | ||
|         }
 | ||
|         xvtil_statbar_set("");
 | ||
|       } //if(ok)..
 | ||
|     } //if(ok)..
 | ||
|     if (ok) // marca sull'install.ini di destinazione l'avvenuta installazione del modulo
 | ||
|       remote_ini->export_module_paragraphs(module, TInstall_ini::default_name(), !is_a_patch);
 | ||
|   } // installazione da directory con zip
 | ||
|   else
 | ||
|     if (!is_a_patch)
 | ||
|     {
 | ||
|       // non c'e' il .ini del modulo ma un unico "install.ini" (es. aggiornamento client)
 | ||
|       //------------------------------------------------
 | ||
|       // (INSTALLAZIONE DA DIRECTORY CON ESEGUIBILI)
 | ||
|       //------------------------------------------------
 | ||
|       remote_ininame = path;
 | ||
|       remote_ininame.add(TInstall_ini::default_name());
 | ||
|       ok = fexist(remote_ininame);
 | ||
|       if (ok)
 | ||
|       {
 | ||
|         TInstall_ini ini(remote_ininame);
 | ||
|         ini.write_protect();
 | ||
|         lastpatch = ini.get_int("Patch", module);
 | ||
|         lastrelease = ini.get("Versione", module);
 | ||
|         if (!can_install(module, ini))
 | ||
|           return false;
 | ||
|   
 | ||
|         TString_array list;
 | ||
|         const int files = ini.build_complete_list(module, list);
 | ||
|         if (files > 0)
 | ||
|         {
 | ||
|           if (patchlevel == 0)
 | ||
|             ok = pre_process(ini, module);
 | ||
|   
 | ||
|           if (ok)
 | ||
|           {
 | ||
|             msg.cut(0) << TR("Copia del modulo ") << module;
 | ||
|             TProgress_monitor pi(files, msg, false);
 | ||
|             TFilename src, dst;
 | ||
|             for (int f = 0; f < files && ok; f++)
 | ||
|             {
 | ||
|               if (!pi.add_status())
 | ||
|               {
 | ||
|                 cancelled = true;
 | ||
|                 break;
 | ||
|               }
 | ||
|               dst = list.row(f).get(0);
 | ||
|               dst.lower();
 | ||
|               src = path;
 | ||
|               src.add(dst);
 | ||
|               const int reboot = needs_reboot(dst);
 | ||
|               if ((reboot & NEW_SYS) != 0 && dst.exist())
 | ||
|               {
 | ||
|                 dst.rtrim(1);
 | ||
|                 dst << '_';
 | ||
|               }
 | ||
|               //copia il file dalla dir sorgenti
 | ||
|               ok = copy_file(src, dst);
 | ||
|               if (ok)
 | ||
|               {
 | ||
|                 if (ok && is_zip_file(src))
 | ||
|                   aga_unzip(src, dst.path());
 | ||
|               
 | ||
|                 if (ok && reboot != NONE)
 | ||
|                   _reboot_program |= reboot;
 | ||
|               }
 | ||
|               else  //se non riesce chiede se proseguire ugualmente
 | ||
|                 ok = yesno_box(TR("Continuare ugualmente ?"));
 | ||
|             }
 | ||
|             ok &= !cancelled;
 | ||
|           }
 | ||
|   
 | ||
|           if (ok)  // marca sull'install.ini di destinazione l'avvenuta installazione del modulo
 | ||
|             ini.export_module_paragraphs(module, ini.default_name(), true);
 | ||
|         } // controllo  esistenza lista di file non vuota per questo modulo
 | ||
|       } // controllo esistenza install.ini
 | ||
|     } // fine installazione da directory con eseguibili
 | ||
| 
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     {
 | ||
|       TInstall_ini ini;
 | ||
|       ini.set("Data", TDate(TODAY), module);
 | ||
|     }
 | ||
|     // Non togliere le parentesi graffe soprastanti per permettere l'aggiornamento fisico del .ini (CON LA CHIAMATA DEL DISTRUTTORE)
 | ||
|     update_version();
 | ||
|   }
 | ||
| 
 | ||
| 
 | ||
|   if (ok && patchlevel == 0)          // Se installo un modulo pricipale ...
 | ||
|   {
 | ||
|     // ... installo DOPO tutte le patches successive
 | ||
|     install_patches(module, lastrelease, lastpatch);
 | ||
|     TInstall_ini ini;
 | ||
|     ok &= post_process(ini, module);
 | ||
|   }
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::get_patches_path(TFilename& path) const
 | ||
| {
 | ||
|   const TEdit_field& www = efield(F_WEB);
 | ||
|   path = www.get();
 | ||
|   if (www.active() && path.full() && is_internet_path(path))
 | ||
|   {
 | ||
|     path.tempdir();
 | ||
|     path.add("www");
 | ||
|     make_dir(path); //crea la directory temporanaea di installazione dove depositare e scompattare gli zip
 | ||
|     return true;
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     path = get(F_PATH);
 | ||
|     // Toglie l'eventual slash finale
 | ||
|     const char last = path.right(1)[0];
 | ||
|     if (last == '/' || last == '\\')
 | ||
|       path.rtrim(1);
 | ||
|   }
 | ||
|   return false;
 | ||
| }
 | ||
| 
 | ||
| void TInstaller_mask::parse_internet_path(TString & http_server, TFilename &http_path) const
 | ||
| {
 | ||
|   http_server = get(F_WEB);
 | ||
|   if (http_server.blank())
 | ||
|   {
 | ||
|     http_server = http_default_path();
 | ||
|     ((TMask*)this)->set(F_WEB, http_server);
 | ||
|   }
 | ||
| 
 | ||
|   if (http_server.starts_with("http://"))
 | ||
|     http_server.ltrim(7);
 | ||
| 
 | ||
|   const int slash = http_server.find('/');
 | ||
|   if (slash > 0)
 | ||
|   {
 | ||
|     http_path = http_server.mid(slash);
 | ||
|     http_server.cut(slash);
 | ||
|   }
 | ||
| 
 | ||
|   //aggiunge lo slash finale se l'utonto l'ha omesso
 | ||
|   if (!http_path.ends_with("/"))
 | ||
|     http_path << '/';
 | ||
| 
 | ||
|   //e' un server redirezionato?
 | ||
|   http_isredirected_server(http_server, http_path);
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::install_patches(const TString& module, const TString& lastrelease, int lastpatch, bool only_newer)
 | ||
| {
 | ||
|   bool ok = true;
 | ||
|   TString_array modules;
 | ||
|   TFilename ininame;
 | ||
|   get_patches_path(ininame);
 | ||
| 
 | ||
|   ininame.add(module);
 | ||
|   ininame << "????a.ini";
 | ||
|   modules.destroy();
 | ||
|   list_files(ininame, modules);
 | ||
|   modules.sort();
 | ||
|   FOR_EACH_ARRAY_ROW(modules, am, arow)
 | ||
|   {
 | ||
|     TString& ininame = *arow;
 | ||
|     ininame.lower();
 | ||
|     const int pos = ininame.find("a.ini");
 | ||
|     CHECKS(pos >= 6, "Invalid installation configuration: ", (const char*)ininame);
 | ||
|     const TString4 patchmodule = ininame.mid(pos-6, 2);
 | ||
|     TConfig ini(ininame, patchmodule);
 | ||
|     const int patchlevel = ini.get_int("Patch");
 | ||
|     const TString16 patchversion = ini.get("Versione");
 | ||
|     if (ok && lastrelease.mid(4) == patchversion.mid(4) // installa solo le patch della stessa ver..
 | ||
|         && (only_newer ? lastpatch < patchlevel : lastpatch <= patchlevel)) // ... e patch superiore o uguale (reinstalla l'ultima patch)
 | ||
|       ok = install(module, patchlevel);
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::update_handler(TMask_field& f, KEY k)
 | ||
| {
 | ||
|   if (k == K_SPACE)
 | ||
|   {
 | ||
|     TInstaller_mask& m = (TInstaller_mask&)f.mask();
 | ||
|     m.autoload();
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::path_handler(TMask_field& fld, KEY key)
 | ||
| {
 | ||
|   bool ok = true;
 | ||
|   if (key == K_TAB && fld.focusdirty())
 | ||
|   {
 | ||
|     TFilename path = fld.get();
 | ||
|     if (path.full())
 | ||
|     {
 | ||
|       if (path.len() == 2 && isalpha(path[0]) && path[1] == ':')
 | ||
|       {
 | ||
|         path << SLASH;
 | ||
|         fld.set(path);
 | ||
|       }
 | ||
|       if (path.exist() || ::is_internet_path(path))
 | ||
|         _curr_mask->autoload();
 | ||
|       else
 | ||
|         ok = fld.error_box(TR("Specificare un percorso valido"));
 | ||
|     }
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::web_handler(TMask_field& fld, KEY key)
 | ||
| {
 | ||
|   bool ok = true;
 | ||
|   if (key == K_TAB && fld.focusdirty())
 | ||
|   {
 | ||
|     TFilename path = fld.get();
 | ||
|     if (path.not_empty())
 | ||
|     {
 | ||
|       if (!path.ends_with("/"))
 | ||
|       {
 | ||
|         path << '/';
 | ||
|         fld.set(path);
 | ||
|       }
 | ||
|       ok = ::is_internet_path(path);
 | ||
|       if (!ok)
 | ||
|         ok = fld.error_box(TR("Specificare un indirizzo valido"));
 | ||
|     }
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // Aggiorna l'install.ini con eventuali modifiche dell'utente su dispath e/o webpath 
 | ||
| // Decisivo in caso di cambio path d'installazione
 | ||
| // Serve a setup (deve essere chiamata in caso di esecuzioni passive di setup, tipo -uw, -uw)
 | ||
| void TInstaller_mask::update_disk_and_web_path()
 | ||
| {
 | ||
|   TInstall_ini ini;
 | ||
|   ini.set("DiskPath", get(F_PATH));
 | ||
|   ini.set("WebPath", get(F_WEB));
 | ||
| }
 | ||
| 
 | ||
| void TInstaller_mask::install_selection()
 | ||
| {
 | ||
|   int nModules = 0;
 | ||
| 
 | ||
|   TString_array& arr = rows_array();
 | ||
|   if (!arr.empty())
 | ||
|   {
 | ||
|     FOR_EACH_ARRAY_ROW(arr, r, row) 
 | ||
|     {
 | ||
|       if (checked(r)) 
 | ||
|         nModules++;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   TProgress_monitor pi(nModules, TR("Installazione"));
 | ||
| 
 | ||
|   //deve poter tener conto del "No Tutti" in caso di installazione da area release
 | ||
|   bool no_to_all = false;
 | ||
|   
 | ||
|   FOR_EACH_ARRAY_ROW(arr, r, row) if (checked(r))
 | ||
|   {
 | ||
|     if (!pi.add_status())
 | ||
|       break;
 | ||
| 
 | ||
|     const TString newver = row->get(C_RELEASE);
 | ||
|     if (newver.blank())
 | ||
|     {
 | ||
|       check(r, false);
 | ||
|       continue;
 | ||
|     }
 | ||
| 
 | ||
|     const TString4 modulo = row->get(C_CODE);
 | ||
|     const TString modesc = dongle().module_name2desc(modulo);
 | ||
|     const int newpatch = row->get_int(C_PATCH);
 | ||
|     const TString oldver = row->get(C_CURRRELEASE);
 | ||
|     const int oldpatch = row->get_int(C_CURRPATCH);
 | ||
| 
 | ||
|     pi.set_text(format(FR("Installazione modulo '%s'"), (const char*)modesc));
 | ||
|     if (version2year(newver) < 2012)
 | ||
|     {
 | ||
|       error_box(FR("Il modulo '%s' non ha una versione valida."), (const char*)modesc);
 | ||
|       continue;
 | ||
|     }
 | ||
| 
 | ||
|     bool ok = true;
 | ||
|     bool is_patch = row->get_char(C_ISPATCH) == 'X';
 | ||
|     bool has_patch = row->get_char(C_ISPATCH) == '+';
 | ||
|     const int cmp = compare_version(oldver, oldpatch, newver, newpatch);
 | ||
| 
 | ||
| 		//versione e patch coincidono
 | ||
|     if (cmp == 0)
 | ||
|       ok = noyes_box(FR("Si desidera reinstallare la versione %s.%d del modulo '%s' ?"), (const char*)newver, newpatch, (const char*)modesc);
 | ||
|     
 | ||
| 		//ci sono ANCHE i pacchi
 | ||
| 		if (!is_patch && cmp > 0)
 | ||
|     {
 | ||
|       TString256 msg;
 | ||
|       msg.format(FR("Si desidera ritornare alla versione %s.%d del modulo '%s' ?\nAttenzione: non <20> garantito il corretto\nfunzionamento di tutti i programmi!"), (const char*)newver, newpatch, (const char*)modesc);
 | ||
|       ok = noyes_box(msg);
 | ||
|     }
 | ||
| 
 | ||
| 		//ci sono SOLO patch da installare
 | ||
|     if (ok && is_patch)
 | ||
|     {
 | ||
|       // installo le patch solo se esiste gi<67> un modulo installato della stessa versione
 | ||
|       if (!oldver.blank() )
 | ||
|       {
 | ||
|         if (compare_version(oldver, 0, newver, 0))	//controlla SOLO la versione indipendentemente dall'anno!
 | ||
|           ok = error_box(FR("Il modulo '%s' installato ha versione %s:\nimpossibile installare le patch della versione %s"),(const char *)modulo,(const char *)oldver,(const char *)newver);
 | ||
|       } else
 | ||
| 	    if (newpatch < oldpatch)
 | ||
| 		  {
 | ||
| 			TString256 msg;
 | ||
| 			msg.format(FR("Si desidera ritornare alla patch %s.%d del modulo '%s' ?\nAttenzione: non e' garantito il corretto\nfunzionamento di tutti i programmi!"), (const char*)newver, newpatch, (const char*)modesc);
 | ||
| 		    ok = noyes_box(msg);
 | ||
| 		  }    
 | ||
|     } //if(ok&&is_patch...
 | ||
| 
 | ||
|     if (ok)
 | ||
|     {
 | ||
|       if (has_patch)
 | ||
|       {
 | ||
|         if (newver == oldver && newpatch >= oldpatch)
 | ||
|         {
 | ||
|           const int basepatch = row->get_int(C_BASEPATCH);
 | ||
|           if (oldpatch >= basepatch)
 | ||
|           {
 | ||
|             if (!no_to_all)
 | ||
|             {
 | ||
|               const int key = yesnoall_box(FR("Si desidera reinstallare l'intero modulo '%s'?"
 | ||
|                                               "\nRispondendo NO verranno installate le sole patch"),
 | ||
|                                               (const char *)modesc);
 | ||
|               switch (key)
 | ||
|               {
 | ||
|               case K_YES:
 | ||
|                 is_patch = true;
 | ||
|                 break;
 | ||
|               case K_SPACE: //se risponde "No Tutti", non deve pi<70> chiederlo e prenderlo sempre per buono
 | ||
|                 is_patch = true;
 | ||
|                 no_to_all = true;
 | ||
|                 break;
 | ||
|               default:
 | ||
|                 is_patch = false;
 | ||
|                 break;
 | ||
|               }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 //se ha gi<67> deciso di NON reinstallare mai i pacchi ("no tutti") allora is_patch <20> sempre true..
 | ||
|                 //..in modo da installare le sole patch
 | ||
|               is_patch = true;
 | ||
|             }
 | ||
|           }
 | ||
|           else 
 | ||
|             is_patch = false; // Quando la versione installata precede la patch base devo reinstallare il modulo!
 | ||
|         }
 | ||
|       }
 | ||
|        
 | ||
|       TFilename path;
 | ||
|       const bool internet = get_patches_path(path);
 | ||
| 
 | ||
|       //richiesto aggiornamento da disco del modulo SY o del modulo SR da manutenzione/installazione moduli!
 | ||
|       if (modulo == "sy" || modulo == "sr")
 | ||
|       {
 | ||
|         if (!run_as_admin())
 | ||
|         {
 | ||
|           error_box("Per installare il modulo sistema <20> necessario eseguire l'applicazione come amministratore");
 | ||
|           break;
 | ||
|         }
 | ||
| 
 | ||
|         if (!internet)
 | ||
|         {
 | ||
|           bool file_copied = false;
 | ||
|           //trova il path della directory setup che e' nell'area con gli zip del cd
 | ||
|           TFilename disk_path = path;
 | ||
|           disk_path.add("setup/");
 | ||
|           TString_array ar;
 | ||
|           const int items = disk_path.exist() ? list_files(disk_path, ar) : 0;
 | ||
|           if (items > 0)
 | ||
|           {
 | ||
|             //copia la dir setup dal disco sovrascrivendo eventuali files gia' presenti
 | ||
|             make_dir("setup");
 | ||
|             TFilename local_file, remote_file;
 | ||
| 
 | ||
|             //preserva l'OEM contenuto in oem.ini della directory setup
 | ||
|             const int old_oem = ini_get_int("setup/oem.ini", "MAIN", "OEM");
 | ||
| 
 | ||
|             FOR_EACH_ARRAY_ROW(ar, r, row)
 | ||
|             {
 | ||
|               local_file = row->mid(path.len() + 1);
 | ||
|               remote_file = *row;
 | ||
|               file_copied = fcopy(remote_file, local_file); //occhio alle maiuscole!!!!
 | ||
|             }
 | ||
|             //riscrive il vecchio valore di oem in oem.ini
 | ||
|             ini_set_int("setup/oem.ini", "MAIN", "OEM", old_oem);
 | ||
|           }
 | ||
| 
 | ||
|           update_disk_and_web_path(); //aggiorna l'install.ini
 | ||
|           //lancia setup in modalita' aggiornamento da disco
 | ||
|           if (test_station_type() == 3)
 | ||
|             _setup_run = xvt_sys_execute("setup\\SetCmpUp.exe -uc", false, false) !=0;
 | ||
|           else
 | ||
|             _setup_run = xvt_sys_execute("setup\\SetCmpUp.exe -ud", false, false) !=0;
 | ||
|         }
 | ||
|         //richiesto aggiornamento via web del modulo SY da manutenzione/installazione moduli!
 | ||
|         else
 | ||
|         {
 | ||
|           bool file_copied = false;
 | ||
|           //trova l'indirizzo web completo
 | ||
|           TString http_server;
 | ||
|           TFilename http_path;
 | ||
|           parse_internet_path(http_server, http_path);
 | ||
|           //copia la dir setup dalla remote dir sovrascrivendo eventuali files gia' presenti
 | ||
|           http_path.add("setup/");
 | ||
|           TString_array ar;
 | ||
|           http_dir(http_server, http_path, ar);
 | ||
|           if (ar.items() > 0)
 | ||
|           {
 | ||
|             make_dir("setup");
 | ||
|             TFilename local_file, remote_file;
 | ||
|             FOR_EACH_ARRAY_ROW(ar, r, row)
 | ||
|             {
 | ||
|               local_file = "setup";
 | ||
|               local_file.add(*row);
 | ||
|               remote_file = http_path;
 | ||
|               remote_file.add(*row);
 | ||
|               //via web NON deve copiare oem.ini perch<63> NON deve poter cambiare il reseller (solo via disco sar<61>..
 | ||
|               //..possibile)
 | ||
|               const bool is_oem_ini = xvt_str_compare_ignoring_case(remote_file.name(), "oem.ini") == 0;
 | ||
|               if (is_oem_ini)
 | ||
|               {
 | ||
|                 const int old_oem = xvt_sys_get_profile_int(local_file, "MAIN", "OEM", -1);
 | ||
|                 file_copied = http_get(http_server, remote_file, local_file); //occhio alle maiuscole!!!!
 | ||
|                 const int new_oem = xvt_sys_get_profile_int(local_file, "MAIN", "OEM", -1);
 | ||
|                 if (new_oem != old_oem)
 | ||
|                 {
 | ||
|                   TString4 str_oem; str_oem << ' ' << old_oem;
 | ||
|                   xvt_sys_set_profile_string(local_file, "MAIN", "OEM", str_oem);
 | ||
|                 }
 | ||
|               }
 | ||
|               else
 | ||
|                 file_copied = http_get(http_server, remote_file, local_file); //occhio alle maiuscole!!!!
 | ||
|             }
 | ||
|           }
 | ||
|           update_disk_and_web_path(); //aggiorna l'install.ini
 | ||
|           //lancia setup in modalita' aggiornamento web 
 | ||
|           _setup_run = xvt_sys_execute("setup\\SetCmpUp.exe -uw", false, false) != 0;
 | ||
|         }
 | ||
|         if (_setup_run) //se riesce a lanciare setup.exe...
 | ||
|         {
 | ||
|           //si suicida...Banzai!
 | ||
|           uncheck(r);
 | ||
|           send_key(K_SPACE, DLG_QUIT);
 | ||
|           return;
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       //installa solo le patch del modulo...
 | ||
|       if (is_patch)
 | ||
|       {
 | ||
|         ok = install_patches(modulo, oldver, oldpatch, false) ; // installa l'ultima patch
 | ||
|         if (!ok)
 | ||
|           message_box(TR("Impossibile installare le patch del modulo '%s'"),(const char *)modesc);
 | ||
|       }
 | ||
|       else    //..installa anche il pacco del modulo
 | ||
|       {
 | ||
|         ok = install(modulo, 0); // installa il modulo
 | ||
|       }
 | ||
|       if (ok)
 | ||
|       {
 | ||
|         _installed = true; // Setta il flag di almeno un modulo installato
 | ||
|         uncheck(r);  //finalmente unchecka i moduli installati
 | ||
|       }
 | ||
|     } //if(ok)...
 | ||
|     else
 | ||
|       uncheck(r); // se non ci sono patch o moduli -> uncheck
 | ||
|   } //FOR_EACH_ARRAY_ROW(arr...
 | ||
|   
 | ||
|   //aggiorna definitivamente i path su install.ini
 | ||
|   update_disk_and_web_path();
 | ||
|   //accoppa i files nelle kill lists e aggiorna install.ini
 | ||
|   kill_files();
 | ||
|   //serve per togliere il check al modulo 'sy' quando viene installato
 | ||
|   force_update();
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::install_handler(TMask_field& fld, KEY key)
 | ||
| {
 | ||
|   if (key == K_SPACE)
 | ||
|   {
 | ||
|     if (_curr_mask->items() == 1)
 | ||
|       _curr_mask->check(0);
 | ||
|     const bool check_on = _curr_mask->check_enabled();
 | ||
|     _curr_mask->enable_check(true);
 | ||
|     const bool some = _curr_mask->one_checked();
 | ||
|     _curr_mask->enable_check(check_on);
 | ||
|     if (some)
 | ||
|       _curr_mask->install_selection();
 | ||
|     else
 | ||
|       error_box(TR("Selezionare uno o pi<70> moduli da installare."));
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TInstaller_mask::tutti_handler(TMask_field& f, KEY k)
 | ||
| {
 | ||
|   if (k == K_SPACE)
 | ||
|   {
 | ||
|     TInstaller_mask & m=(TInstaller_mask &) f.mask();
 | ||
|     if (m.check_enabled())
 | ||
|     {
 | ||
|       if (m.one_checked())
 | ||
|         m.uncheck(-1);
 | ||
|       else
 | ||
|         m.precheck_modules(false);
 | ||
|     }
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller_mask::on_key(KEY key)
 | ||
| {
 | ||
|   bool ok = true;
 | ||
|   switch (key)
 | ||
|   {
 | ||
|     case K_F7: autoload(); break;
 | ||
|     case K_F8: field(DLG_USER).on_hit(); break;
 | ||
|     default  : ok = TArray_sheet::on_key(key); break;
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| //metodo per controllare se la directory indicata contiene una installazione buona di campo
 | ||
| bool TInstaller_mask::is_program_dir(const TFilename& path)
 | ||
| {
 | ||
|   //controlla l'esistenza di alcuni files chiave di campo
 | ||
|   const char* const essential[] = {"install.ini", "campo.ini", "campo.aut", "ba0.exe", "xvaga.dll", NULL };
 | ||
|   bool ok = true;
 | ||
|   for (int i = 0; ok && essential[i]; i++)
 | ||
|   {
 | ||
|     TFilename work_path = path;
 | ||
|     work_path.add(essential[i]);
 | ||
|     ok = work_path.exist();
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| TInstaller_mask::TInstaller_mask()
 | ||
|                : TArray_sheet(0, 0, 0, 0, TR("Installazione"),
 | ||
|                 HR("@1|Modulo@32|Cod.@3|Versione da\ninstallare@11|Liv.\nPatch@6|Data\nRilascio@10|Versione\nInstallata@10|Liv.\nPatch@6|Data\nInstallazione@13|Aggiornamento|Patch Base|OEM@10"),
 | ||
|                 0x18, 4)
 | ||
| {
 | ||
|   add_button(F_INSTALL, TR("Installa"), '\0', TOOL_ELABORA);   // NON mettere 'I'
 | ||
|   add_button(F_UPDATE, TR("Aggiorna Lista"), '\0', TOOL_CONVERT);
 | ||
|   add_button(DLG_NULL, "", '\0');
 | ||
|   add_button(DLG_INFO, TR("Info"), K_F2, TOOL_INFO);
 | ||
|   add_button(DLG_HELP, TR("Help"), K_F1, TOOL_HELP);
 | ||
|   xvt_toolbar_set_last_tool(toolbar(), DLG_QUIT);
 | ||
| 
 | ||
|   _station_type = test_station_type();
 | ||
|   _curr_mask = this;
 | ||
|   _installed = false;
 | ||
|   _reboot_program= NONE;
 | ||
| 
 | ||
|   //in base al tipo di installazione che rileva decide se puo' effettuare aggiornamenti via web (un client..
 | ||
|   //..non puo' fare aggiornamenti da web!!!)
 | ||
|   TToken_string installada; 
 | ||
|   installada.add(PR("Installa da disco")); 
 | ||
|   installada.add(PR("Installa da web  "));
 | ||
|   TRadio_field& rf = add_radio(F_TYPE, 0, "", 0, 0, 23, "0|1", installada);
 | ||
|   *rf.message(0, true) = "DISABLE,207|ENABLE,201";
 | ||
|   *rf.message(1, true) = "DISABLE,201|ENABLE,207";
 | ||
|   add_string(F_PATH, 0, "", 23, 1, 256, "B", 56).set_selector('D', EMPTY_STRING);
 | ||
|   add_string(F_WEB, 0, "", 23, 2, 256, "", 56);
 | ||
|   set(F_TYPE, "0", 0x1);
 | ||
| 
 | ||
|   //deve conoscere i path adesso per poter testare se sono ok 
 | ||
|   TInstall_ini ini;
 | ||
|   TFilename path = ini.get("DiskPath");
 | ||
|   TFilename webpath = ini.get("WebPath");
 | ||
| 
 | ||
|   //un client non puo' scegliere a caso da dove aggiornarsi! Solo dal suo server!
 | ||
|   if (_station_type == 3)
 | ||
|   {
 | ||
|     rf.disable();
 | ||
|     bool ko = !is_program_dir(path);
 | ||
|     if (ko)
 | ||
|       warning_box(TR("La cartella origine dei programmi NON <20> valida!\nSelezionarne una valida e premere 'Invio'."));
 | ||
|     enable(F_PATH, ko);
 | ||
|   }
 | ||
| 
 | ||
|   add_string(F_CURPATH, 0, PR("Installa in           "), 1, 3, 80, "D", 56);
 | ||
| 
 | ||
|   set_handler(F_PATH, path_handler);
 | ||
|   set_handler(F_WEB, web_handler);
 | ||
|   set_handler(F_INSTALL, install_handler);
 | ||
|   set_handler(F_UPDATE, update_handler);
 | ||
|   set_handler(DLG_USER, tutti_handler);
 | ||
| 
 | ||
|   //se il webpath <20> vuoto o di test, propone quello in oem.ini; non ammette che possa essere proposto un path..
 | ||
|   //..di tipo test per impedire all'utonto di aggiornarsi da test prima di essere passato da release
 | ||
|   if (webpath.empty() || webpath.find("test") > 0 || webpath.find("85.18.") >= 0)
 | ||
|     webpath = http_default_path();
 | ||
| 
 | ||
|   set(F_PATH, path);
 | ||
|   set(F_WEB, webpath);
 | ||
|   //..fine costruzione maschera di installazione
 | ||
| 
 | ||
|   //decide quale e' il percorso di installazione
 | ||
|   //ha un cd o un disco di rete -> si aggiorna da questo...
 | ||
|   if (path.exist())
 | ||
|   {
 | ||
|     if (efield(F_PATH).active() || _station_type == 3)  // Per i client <20> obbligatorio installare da disco
 | ||
|       autoload(); 
 | ||
|   }
 | ||
|   else  //senno' cerca su internet se trova un path internet completo e la connessione funzionante
 | ||
|   {
 | ||
|     if (_station_type != 3 && webpath.find("//") > 0)
 | ||
|     {
 | ||
|       set(F_TYPE, "1", 0x1);
 | ||
|       //autoload();  // Niente autoload!
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   DIRECTORY dir;
 | ||
|   xvt_fsys_get_dir(&dir);
 | ||
|   xvt_fsys_convert_dir_to_str(&dir, path.get_buffer(), path.size());
 | ||
|   set(F_CURPATH, path);
 | ||
| }
 | ||
| 
 | ||
| TInstaller_mask::~TInstaller_mask()
 | ||
| {
 | ||
|   _curr_mask = NULL;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // Programma principale
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TInstaller : public TSkeleton_application
 | ||
| {
 | ||
| protected:
 | ||
|   TInstaller_mask* _m;
 | ||
| 
 | ||
| protected:
 | ||
|   virtual bool create();
 | ||
|   virtual bool use_files() const { return false; }
 | ||
|   virtual bool test_assistance_year() const;
 | ||
|   virtual void main_loop();
 | ||
|   void convert_archives();
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| bool TInstaller::test_assistance_year() const
 | ||
| {  
 | ||
|   // Per il momento lascia continuare: ci pensa poi la create
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| bool TInstaller::create()
 | ||
| {
 | ||
|   if (!TApplication::test_assistance_year(true))
 | ||
|   {
 | ||
|     TExternal_app attivazione("ba1 -4");
 | ||
|     attivazione.run();
 | ||
|     dongle().login();  // Rilegge anno assistenza
 | ||
|   }
 | ||
|   else
 | ||
|     update_dninst(false);  // Aggiorna se necessario
 | ||
| 
 | ||
|   //crea la maschera di installazione
 | ||
|    _m = new TInstaller_mask();
 | ||
| 
 | ||
|    //se e' un client
 | ||
|   if (_m->station_type() == 3)
 | ||
|   {  
 | ||
|     _m->disable_check();
 | ||
|     _m->disable(F_UPDATE);
 | ||
|     _m->disable(DLG_USER);  
 | ||
|   } 
 | ||
|   else  //se e' standalone o server...
 | ||
|   {
 | ||
|     if (user() != ::dongle().administrator())
 | ||
|       return error_box(TR("Solo l'amministratore puo' aggiornare questa postazione!"));
 | ||
|   }
 | ||
| 
 | ||
|   return TSkeleton_application::create();
 | ||
| }
 | ||
| 
 | ||
| void TInstaller::convert_archives()
 | ||
| {
 | ||
|   bool conv = true;
 | ||
|   if (is_power_station())
 | ||
|     conv = yesno_box(TR("Si desidera convertire gli archivi ora?"));
 | ||
|   if (conv)
 | ||
|   {
 | ||
|     _m->backup();
 | ||
|     // Lancia conversione: ba1 -0 -C -uADMIN
 | ||
|     TExternal_app conversion("ba1 -0 -C");
 | ||
|     conversion.run();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TInstaller::main_loop()
 | ||
| {
 | ||
|   _m->run();
 | ||
|   if (_m->run_conversion() && _m->station_type() < 3) // Almeno un trr installato e non e' client->conversione ammessa
 | ||
|   {
 | ||
|     convert_archives();
 | ||
|   }
 | ||
| 
 | ||
|   //controlla se ha lanciato setup.exe prima di chiudersi; se non lo ha fatto -> e' a fine installazione..
 | ||
|   //..normale (moduli non SY) e quindi lancia ba0.exe
 | ||
|   const bool setup_launched = _m->setup_run();
 | ||
|   delete _m; _m = NULL;
 | ||
|   if (!setup_launched)
 | ||
|   {
 | ||
|     TExternal_app ba0("ba0.exe");
 | ||
|     ba0.run(true, true, false); // run asynchronous and not iconized!
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| int ba1700(int argc, char* argv[])
 | ||
| {
 | ||
|   TInstaller app;
 | ||
|   app.run(argc, argv, TR("Installazione moduli"));
 | ||
|   return 0;
 | ||
| }
 |