campo-sirio/ba/ba1700.cpp
luca bcc054fcb2 Patch level :nopatch 2.0
Files correlati     :ba1.exe & co.
Ricompilazione Demo : [ ]
Commento            :sistemati alcuni errori di riporto sulla versione 32 bit


git-svn-id: svn://10.65.10.50/trunk@10186 c028cbd2-c16b-5b4b-a496-9718f37d4682
2002-04-26 10:47:22 +00:00

1383 lines
37 KiB
C++
Executable File
Raw Blame History

#include <applicat.h>
#include <colors.h>
#include <defmask.h>
#include <dongle.h>
#include <execp.h>
#include <isamrpc.h>
#include <os_dep.h>
#include <progind.h>
#include <sheet.h>
#include <utility.h>
#include <prefix.h>
#include <urldefid.h>
#include "ba1.h"
#include "ba1500.h"
#include "ba1600.h"
#include "ba1700a.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
#ifdef _DEMO_
const char* const http_default_path = "/aga/eurodemo/zipdemo/";
#else
const char* const http_default_path = "/aga/euro/zip/";
#endif
HIDDEN int compare_version(const char* v1, int p1, const char* v2, int p2)
{
TString16 ver1(v1), ver2(v2);
ver1.trim();
if (ver1.len() == 4)
ver1.insert((v1[0] == '9') ? "19" : "20", 0);
ver2.trim();
if (ver2.len() == 4)
ver2.insert((v2[0] == '9') ? "19" : "20", 0);
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);
}
bool is_internet_path(const TString& addr)
{
if (addr.compare("www.", 4, TRUE) == 0)
return TRUE;
if (addr.compare("http:", 5, TRUE) == 0)
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;
word _year_assist;
bool _installed; // Flag per verificare se almeno un modulo e' stato installato
enum {NONE, NEW_MENU, NEW_MENUPRG, NEW_INSTALLER} _reboot_program;
protected: // TSheet
virtual bool on_key(KEY key);
static bool quit_handler(TMask_field& f, KEY k);
static bool tutti_handler(TMask_field& f, KEY k);
int get_module_number(const char * module) const;
protected:
static bool path_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, bool patch);
int precheck_modules(bool only_newer=TRUE);
void update_version();
bool move_file(const TFilename& fromdir, const TFilename& file, const char* dir) 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_internet_path(TFilename &ininame );
void parse_internet_path(TString & http_server, TFilename &http_path );
public:
bool installed() { return _installed;}
bool autoload();
bool install(const TString& module, int patch);
TInstaller_mask();
virtual ~TInstaller_mask();
};
TInstaller_mask* TInstaller_mask::_curr_mask = NULL;
// 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();
bool ok = ini.set_paragraph(module);
if (ok)
{
const int numpatch = ini.get_int("Patch");
TString16 strpatch;
if (numpatch > 0)
strpatch.format("%03d", 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);
if (pos==-1)
add(row);
else
insert(row,pos);
}
return ok;
}
// Copia nello sheet i dati di un modulo prendendoli da un .ini
bool TInstaller_mask::add_header(TConfig& ini, const TString& module, bool patch)
{
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;
}
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++)
{
TString16 s1 = ts1.get(i);
const char* s2 = ts2.get(i);
res = s1.compare(s2);
}
return res;
}
int TInstaller_mask::precheck_modules(bool only_newer)
{
const int tot = int(items());
TString16 release,currrelease;
int patchlevel,modnumber;
for (int r = 0; r < tot; r++)
{
release = row(r).get(C_RELEASE);
patchlevel = row(r).get_int(C_PATCH);
currrelease = row(r).get(C_CURRRELEASE);
modnumber=get_module_number(row(r).get(C_CODE));
if (modnumber >= 0 &&
!release.blank() &&
((release > currrelease) ||
(release == currrelease
&& (only_newer ? patchlevel>row(r).get_int(C_CURRPATCH): patchlevel>=row(r).get_int(C_CURRPATCH)) ))
&& main_app().has_module(modnumber,CHK_DONGLE) )
{
// checca il modulo o la patch se ho installata la stessa versione
const bool chk = row(r).get_char(C_ISPATCH) != 'X' || release == row(r).get(C_CURRRELEASE);
check(r,chk );
}
}
force_update(); // Indispensabile per vedere le righe aggiornate
return tot;
}
int TInstaller_mask::get_module_number(const char * module) const
{
int aut = -1;
if (module && * module)
{
TScanner scanner(AUT_FILE);
bool ok = FALSE;
for (aut = 0; scanner.line() != ""; aut++)
if (strncmp(scanner.token(), module, 2) == 0) { ok = TRUE; break; }
}
return ok ? aut : -1;
}
void TInstaller_mask::update_version()
{
TInstall_ini ini;
TString_array& array = rows_array();
FOR_EACH_ARRAY_ROW_BACK(array, m, row)
{
if (*row->get(C_CODE) != ' ')
{
const TString16 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");
TString16 strpatch;
if (numpatch > 0) strpatch.format("%03d", numpatch);
row->add(oldver, C_CURRRELEASE);
row->add(strpatch, C_CURRPATCH);
row->add(ini.get("Data"), C_CURRDATAREL);
}
}
force_update();
}
// 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;
TFilename path ;
TFilename ininame;
const bool internet = get_internet_path(path);
if (internet)
{
parse_internet_path(http_server,http_path );
/* http_server = get(F_PATH);
if (http_server.compare("http://", 7, TRUE) == 0)
http_server.ltrim(7);
const int slash = http_server.find('/');
if (slash > 0)
{
http_path = http_server.mid(slash);
if (http_path.right(1) != "/")
http_path << '/';
http_server.cut(slash);
}
else
http_path = http_default_path;*/
make_dir(path);
ininame = path;
ininame.add(TInstall_ini::default_name());
if (ininame.exist() && yesno_box("Si desidera svuotare la cache dei files scaricati dal sito?"))
{
TString_array list;
TFilename name = path; name.add("*.*");
::list_files(name, list);
FOR_EACH_ARRAY_ROW(list, i, row)
::remove(*row);
}
if (!ininame.exist())
{
bool httpresult;
TFilename remote_ini = http_path;
remote_ini << TInstall_ini::default_name();
{
TIndwin contacting(60,"Sto contattando il server HTTP...",FALSE,FALSE);
httpresult=http_get(http_server, remote_ini, ininame);
}
if (!httpresult)
return error_box("Impossibile trasferire %s da %s",
(const char*)remote_ini, (const char*)http_server);
}
}
if (path.exist())
{
ininame = path;
ininame.add(TInstall_ini::default_name());
}
else
return error_box("Specificare un percorso valido");
TWait_cursor hourglass;
// !?!?!? modifica per correggere il bug di libreria su _parked dei TSheet:
// !?!?!? (uso della stringa _park e dell'indice _parked )
// !?!?!? rimuovere appena si <20> corretto l'errore
// for (short pisellone =0; pisellone<100; pisellone++) add("");
// !?!?! fine modifica
destroy();
force_update();
ininame=path;
ininame.add(TInstall_ini::default_name());
TString_array modules;
if (ininame.exist())
{
// Presente il file ini generale "install.ini"
TInstall_ini ini(ininame);
ini.list_paragraphs(modules);
FOR_EACH_ARRAY_ROW(modules, i, row)
{
const TString& module = *row;
if (module[0] == '_' || module.len() == 2)
{
if (module[0] == '_')
add_header(ini, module, FALSE);
else
add_module(ini, module, FALSE);
}
}
}
else
{
// Presenti i singoli file ini dei moduli
ininame = path;
ininame.add("??inst.ini");
list_files(ininame, modules);
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 TString16 module = ininame.mid(pos-2, 2);
TConfig ini(ininame, module);
add_module(ini, module, FALSE);
}
}
// add patches
modules.destroy();
if (internet)
{
http_dir(http_server, http_path, modules);
for (int i = modules.last(); i >= 0; i--)
{
TString& str = modules.row(i);
if (str.match("??0???A.INI") || str.match("??0???a.ini"))
{
TFilename remote = http_path;
remote << str;
ininame = path;
ininame.add(str);
if (!ininame.exist() && !http_get(http_server, remote, ininame))
{
error_box("Errore di trasferimento del file %s", (const char*)remote);
modules.destroy(i);
}
str = ininame;
}
else
modules.destroy(i);
}
modules.pack();
}
else
{
ininame = path;
ininame.add("??0???a.ini");
list_files(ininame, modules);
}
modules.sort(); // sort to have patches in patchlevel order
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 TString16 module = ininame.mid(pos-6, 2);
TConfig ini(ininame, module);
ini.write_protect();
for (int r = int(items()-1); r >=0; r--)
if (module == row(r).get(C_CODE))
break;
if (r >= 0)
{
const TString16 patchversion = ini.get("Versione");
const int patchlevel = ini.get_int("Patch");
TToken_string& row = mask_rows.row(r);
if (patchversion == row.get(C_RELEASE) // se le versioni corrispondono ...
&& patchlevel > row.get_int(C_PATCH)) // ..e il patchlevel <20> superiore
{
TString16 patch; patch.format("%03d", patchlevel); //aggiunge zeri per avere 3 cifre sempre
row.add(patch, C_PATCH); // aggiorna il patchlevel mostrato per il modulo
if (*row.get(C_ISPATCH)<=' ') // se era un modulo ...
row.add("+", C_ISPATCH); // .....setta la presenza di patches
}
}
else
add_module(ini, module, TRUE);
}
update_version();
const bool ok = precheck_modules() > 0;
if (!ok)
error_box("Non e' stato trovato nessun modulo da installare\n"
"in %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.blank())
{
TWait_cursor hourglass;
TExternal_app app(cmd);
ok = app.run() == 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)
{
TInstall_ini curini;
if (curini.demo() != ini.demo())
{
TString msg;
msg << "Attenzione: Non e' possibile installare la versione ";
msg << (ini.demo() ? "dimostrativa" : "normale");
msg << " nella cartella della versione ";
msg << (curini.demo() ? "dimostrativa" : "normale");
return error_box(msg);
}
const TString& version = ini.version(module);
const word year = version2year(version);
if (year < 1997)
return error_box("Il modulo '%s' non ha una versione valida.", module);
#ifndef _DEMO_
if (year > _year_assist)
return error_box("Per installare la versione %s del modulo '%s'\n"
"occorre il contratto di assistenza per l'anno %d.",
(const char*)version, module, year);
#endif
TAuto_token_string altri(ini.get("Moduli", module));
if (stricmp(module, "ba") != 0 && altri.get_pos("ba") < 0)
altri.add("ba"); // La base e' obbligatoria per tutti
bool ok = TRUE;
TString submodule;
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 << "L'installazione del modulo '" << module
<< "'\nrichiede la presenza del modulo '" << submodule
<< "':\nSi desidera procedere alla sua installazione?";
ok = yesno_box(msg);
if (ok)
ok = install(submodule, 0);
}
}
}
return ok;
}
// sposta il file dal direttorio temporaneo a quello passato come destinazione
// from: direttorio di partenza
// file: nome del file con path completo da spostare (pu<70> includere sottodirettori)
// todir: direttorio destinazione (si assume che esista gi<67>)
bool TInstaller_mask::move_file(const TFilename& from, const TFilename& file, const char* todir) const
{
TFilename dest(todir);
const char *fname=file.mid(from.len()+1);
if (stricmp(fname,"ba0.exe")==0)
dest.add("BA0.EX_");
else if (stricmp(fname,"ba1.exe")==0)
dest.add("BA1.EX_");
else
dest.add(fname);
if (!dest.exist())
{
TToken_string dirs((const char * )(dest.path()),'\\');
// file contains non existent subdir specification ?
TFilename subdir;
for (int c=0; c < dirs.items()-1; c++)
{
subdir.add(dirs.get(c));
if (subdir.right(1) == ":" )
subdir << '\\';
if (!subdir.exist() )
// build destination directory
make_dir(subdir);
}
}
const long filesize = fsize(file);
bool space_ok = FALSE;
while (!space_ok)
{
/*
int disk = 0;
if (dest[1] == ':')
{
const char letter = toupper(dest[0]);
disk = 'A' - letter + 1;
}
struct _diskfree_t drive;
_dos_getdiskfree(disk, &drive);
const unsigned requested_clusters = unsigned(filesize / drive.sectors_per_cluster / drive.bytes_per_sector) + 1;
space_ok = requested_clusters <= drive.avail_clusters;
*/
space_ok = os_test_disk_free_space(dest, filesize);
if (!space_ok)
{
TString msg;
msg << "Lo spazio su disco e' insufficiente:\n";
if (::os_is_removable_drive(todir))
{
msg << "Inserire un nuovo disco e ritentare?";
if (!yesno_box(msg))
return FALSE;
}
else
return error_box(msg);
}
}
bool write_ok = TRUE;
bool user_retry = FALSE;
do
{
write_ok = ::fcopy(file, dest);
if (write_ok)
::remove(file);
else
user_retry = yesno_box("Errore di copia del file %s.\nSi desidera ritentare?",
(const char*)file);
} while (!write_ok && user_retry);
if (write_ok && strcmp(dest.ext(),"men")==0)
((TInstaller_mask *)this)->_reboot_program=NEW_MENU;
return write_ok;
}
bool TInstaller_mask::move_module(const TString& module, TInstall_ini& ini, bool update) const
{
bool ok = TRUE;
TFilename src; src.tempdir();
const TString& dst = get(F_CURPATH);
const TFilename tempdir(src);
TString_array list;
ini.build_list(module, list);
FOR_EACH_ARRAY_ROW(list, f, file)
{
src = tempdir;
src.add(file->get(0));
if (update)
{
const bool move_ok = move_file(tempdir, src, dst);
if (!move_ok)
ok = update = FALSE;
}
if (!update)
::remove(src);
}
return ok;
}
KEY TInstaller_mask::askdisk(TString & path, TFilename & cmdline, int d, int dischi, const char * modulo)
{
TMask retry_mask("Inserimento dischi",1,80,10);
retry_mask.add_static((F_PATH==101 ? 102:101),0,
format("Inserire il disco %d di %d del modulo'%s' nell' unit<69> indicata", d, dischi, modulo)
,2,2);
retry_mask.add_static(F_PATH+3,0,"oppure indicare un percorso diverso",2,3);
retry_mask.add_string(F_PATH,0,"",2,5,48);
retry_mask.add_button(DLG_OK,0,"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("Il percorso indicato non e' valido");
}
} while (TRUE);
return k;
}
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_internet_path(path);
if (internet)
parse_internet_path(http_server,http_path );
const bool is_a_patch=(patchlevel > 0);
TFilename ininame = path;
ininame.add(module);
if (is_a_patch)
{
TString16 name;
name.format("%04da.ini", patchlevel);
ininame << name;
}
else
ininame << "inst.ini";
if (internet && !ininame.exist())
{
TFilename remote = ininame.name();
remote.insert(http_path, 0);
http_get(http_server, remote, ininame);
}
if (ininame.exist())
{
// esiste un particolare .ini con formato XXinst.ini (moduli) o con XX9999a.ini (patch)
// (installazione da directory con .zip)
TInstall_ini *ini;
ini = new TInstall_ini(ininame);
ini->write_protect();
lastpatch=ini->get_int("Patch",module);
lastrelease=ini->get("Versione",module);
if (!can_install(module, *ini))
{
delete ini;
return FALSE;
}
const int dischi = ini->get_int("Dischi", module);
ok = dischi > 0;
if (!ok)
{
return error_box("Impossibile determinare il numero dei dischetti in %s",ininame.name());
}
else
{
if (patchlevel==0)
ok = pre_process(*ini, module);
if (!ok)
{
delete ini;
return FALSE;
}
}
// ***************
// decompressione
msg="Decompressione";
if (is_a_patch)
msg << " della patch " << patchlevel ;
msg << " del modulo '" << module << "' in corso...";
TProgind pi(dischi, msg, FALSE, TRUE);
TFilename tempdir; tempdir.tempdir();
TFilename cmdline;
for (int d = 1; d <= dischi && ok; d++)
{
cmdline = path;
cmdline.add(module);
if (patchlevel > 0)
{
TString16 name;
name.format("%04da", patchlevel);
cmdline << name;
}
else
cmdline << "inst";
cmdline << d << ".zip";
if (internet && !cmdline.exist())
{
TFilename remote = cmdline.name();
remote.insert(http_path, 0);
http_get(http_server, remote, cmdline);
}
ok = cmdline.exist();
while (!ok)
{
if (askdisk(path,cmdline,d,dischi,(const char*)ini->get("Descrizione"))==K_QUIT)
break;
ok = fexist(cmdline);
if (!ok)
message_box("Impossibile trovare %s\n",(const char*)cmdline);
}
if (ok)
{
const long required = fsize(cmdline) * (dischi-d+1) * 4;
if (!os_test_disk_free_space(tempdir, required))
{
ok = yesno_box("Lo spazio su disco potrebbe essere insufficiente:\n"
"Si desidera continuare ugualmente?");
}
}
if (ok)
{
TWait_cursor hourglass;
cmdline.insert("unzip.pif -o ", 0);
cmdline << " -d " << tempdir;
TExternal_app app(cmdline);
ok = app.run(FALSE, FALSE, FALSE, FALSE) == 0;
pi.addstatus(1);
}
}
// ***************
// trasferimento
if (ok)
{
// si assicura che sia leggibile il .ini del primo disco
do {
cmdline = path;
cmdline.add(ininame.name());
ok = fexist(cmdline);
if (!ok)
{
if (askdisk(path,cmdline,1,dischi,(const char*)ini->get("Descrizione"))==K_QUIT)
break;
ok = fexist(cmdline);
if (!ok)
message_box("Impossibile trovare %s\n",(const char*)cmdline);
else
{
delete ini;
ini = new TInstall_ini (cmdline);
}
}
} while (!ok);
if (ok)
{
msg.cut(0);
msg << "Aggiornamento del modulo '" << module << "' in corso...";
pi.set_text(msg);
ok = move_module(module, *ini, TRUE);
TAuto_token_string altri(ini->get("Moduli", module));
FOR_EACH_TOKEN(altri, mod)
{
TAuto_token_string altri(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 curini;
const TString16 curver = curini.version(submod);
const int curpatch = curini.patch(submod);
const TString16 reqver = ini->version(submod);
const int reqpatch = ini->patch(submod);
int distance = compare_version(reqver, reqpatch, curver, curpatch);
upd = distance > 0;
}
ok &= move_module(submod, *ini, upd);
if (upd && ok) // marca sull'install.ini di destinazione l'avvenuta installazione del sottomodulo "esterno"
ini->export_paragraph(submod, ini->default_name(),!is_a_patch);
}
}
}
}
}
if (ok) // marca sull'install.ini di destinazione l'avvenuta installazione del modulo
ini->export_module_paragraphs(module, 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"
// (installazione da directory con eseguibili)
ininame = path;
ininame.add(TInstall_ini::default_name());
ok = fexist(ininame);
if (ok)
{
TInstall_ini ini(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);
msg << "Copia del modulo '" << module << "' in corso ...";
TProgind pi(files, msg, TRUE, TRUE);
TFilename src, dst;
for (int f = 0; f < files && ok; f++)
{
pi.addstatus(1);
dst = list.row(f).get(0);
dst.lower();
src = path;
src.add(dst);
if (dst=="ba1.exe")
dst="ba1.ex_";
if (dst=="ba0.exe")
dst="ba0.ex_";
ok = fcopy(src, dst);
cancelled = pi.iscancelled();
}
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("DiskPath", get(F_PATH));
ini.set("Data", TDate(TODAY), module);
ini.update_prices(ininame);
}
// 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_internet_path(TFilename &ininame )
{
ininame = get(F_PATH);
if (is_internet_path(ininame))
{
ininame.tempdir();
ininame.add("www");
return TRUE;
}
return FALSE;
}
void TInstaller_mask::parse_internet_path(TString & http_server, TFilename &http_path )
{
http_server = get(F_PATH);
if (http_server.compare("http://", 7, TRUE) == 0)
http_server.ltrim(7);
const int slash = http_server.find('/');
if (slash > 0)
{
http_path = http_server.mid(slash);
if (http_path.right(1) != "/")
http_path << '/';
http_server.cut(slash);
}
else
http_path = http_default_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_internet_path(ininame);
ininame.add(module);
ininame << "0???a.ini";
modules.destroy();
list_files(ininame, modules);
modules.sort(); // sort by patch number
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 TString16 patchmodule = ininame.mid(pos-6, 2);
TConfig ini(ininame, patchmodule);
const int patchlevel = ini.get_int("Patch");
const char * patchversion = ini.get("Versione");
if (ok && lastrelease == patchversion // 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.not_empty())
{
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("Specificare un percorso valido");
}
}
return ok;
}
void TInstaller_mask::install_selection()
{
TString_array& arr = rows_array();
FOR_EACH_ARRAY_ROW(arr, r, row) if (checked(r))
{
const TString newver = row->get(C_RELEASE);
if (newver.blank())
{
check(r, FALSE);
continue;
}
const TString modulo = row->get(C_CODE);
const int newpatch = row->get_int(C_PATCH);
const TString oldver = row->get(C_CURRRELEASE);
const int oldpatch = row->get_int(C_CURRPATCH);
if (version2year(newver) < 1998)
{
error_box("Il modulo '%s' non ha una versione valida.", (const char*)modulo);
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);
if (cmp == 0)
ok = noyes_box("Si desidera reinstallare la versione %s.%d del modulo '%s' ?", (const char*)newver, newpatch, (const char*)modulo);
if (!is_patch && cmp > 0)
{
TString256 msg;
msg.format("Si desidera ritornare alla versione %s.%d del modulo '%s' ?\n"
"Attenzione: non e' garantito il corretto\n"
"funzionamento di tutti i programmi!", (const char*)newver, newpatch, (const char*)modulo);
ok = noyes_box(msg);
}
if (ok && is_patch)
{
// installo le patch solo se esiste gi<67> un modulo installato della stessa versione
if (!oldver.blank() )
{
if (oldver != newver)
ok =error_box("Il modulo '%s' installato ha versione %s:\nimpossibile installare le patch della versione %s",(const char *)modulo,(const char *)oldver,(const char *)newver);
} else
ok =FALSE;//error_box("Impossibile installare le patch perche' il modulo '%s' non e' installato",(const char *)modulo);
}
if (ok)
{
if (has_patch)
{
if (newver == oldver && newpatch >= oldpatch &&
!noyes_box("Si desidera reinstallare l'intero modulo '%s'?\n"
"Rispondendo NO verranno installate le sole patch",(const char *)modulo))
{
is_patch = TRUE;
}
}
if (is_patch)
{
ok = install_patches(modulo, oldver, oldpatch, FALSE) ; // installa l'ultima patch
if (!ok)
message_box("Impossibile installare le patch del modulo '%s'",(const char *)modulo);
}
else
ok = install(modulo, 0); // installa il modulo
if (ok)
_installed = TRUE; // Setta il flag di almeno un modulo installato
if (ok)
check(r, FALSE);
}
else
check(r,FALSE); // uncheck
}
if (installed())
message_box("Installazione conclusa");
}
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("Selezionare uno piu' moduli da installare.");
}
return TRUE;
}
bool TInstaller_mask::quit_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TInstaller_mask & m=(TInstaller_mask &) f.mask();
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)
return noyes_box("Alcuni moduli sono selezionati per l'installazione.\nConfermare l'uscita");
}
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;
}
TInstaller_mask::TInstaller_mask()
: TArray_sheet(0, 0, 0, 0, "Installazione",
"@1|Modulo@30|Cod.|Versione da\ninstallare@11|Livello\nPatch@8|Data\nRilascio@10|Versione\nInstallata@10|Livello\nPatch@8|Data\nInstallazione@13|Aggiornamento",
0x18, 3)
{
_curr_mask = this;
_installed = FALSE;
_reboot_program= NONE;
add_string(F_PATH, 0, "Installa da ", 1, 1, 50);
add_string(F_CURPATH, 0, "Installa in ", 1, 2, 50, "D");
//TMask::add_button(F_UPDATE, 0, "Rileggi", 60,1,9,1,""/*,BMP_LINK*/);
add_button(F_UPDATE, "Rileggi", '\0');
//TMask::add_button(F_INSTALL, 0, "Installa", 60,1,9,1,""/*,BMP_LINK*/);
add_button(F_INSTALL, "Installa", '\0'); // NON mettere 'I'
set_handler(F_PATH, path_handler);
set_handler(F_INSTALL, install_handler);
set_handler(F_UPDATE, update_handler);
set_handler(DLG_QUIT, quit_handler);
set_handler(DLG_USER, tutti_handler);
TDongle dongle; dongle.login(); dongle.logout();
_year_assist = dongle.year_assist();
TInstall_ini ini;
TFilename path = ini.get("DiskPath");
set(F_PATH, path);
const bool floppy = os_is_removable_drive(path);
if (path.not_empty() && !floppy && !is_internet_path(path))
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;
TString msg;
TFilename ba0exfile("ba0.ex_"),ba1exfile("ba1.ex_");
switch (_reboot_program)
{
case NEW_MENU:
msg << "sono stati aggiornati i menu'";
default:
if (ba0exfile.exist())
{
if (!msg.blank())
msg << " e ";
else
msg << "e' stato ";
msg << "aggiornato il navigatore dei menu'";
}
if (ba1exfile.exist())
{
if (!msg.blank())
msg << " e ";
else
msg << "e' stato ";
msg << "aggiornato l'installatore";
}
}
if (!msg.empty())
{
msg.insert("Attenzione:");
msg << ".\nE' necessario uscire e rientrare dal programma";
warning_box(msg);
}
}
///////////////////////////////////////////////////////////
// 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();
bool testdatabase() const;
bool testprograms() const;
};
bool TInstaller::testdatabase() const
{
TConfig ini(CONFIG_INSTALL);
return ini.get("TestDatabase","Main",-1,"Y") != "N";
}
bool TInstaller::testprograms() const
{
TConfig ini(CONFIG_INSTALL);
char c = ini.get("TestPrograms","Main",-1,"N")[0];
return c == 'X' || c == 'Y';
}
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())
{
TExternal_app attivazione("ba1 -4");
attivazione.run();
dongle().login(); // Rilegge anno assistenza
}
if (testprograms())
{
_m = new TInstaller_mask() ;
_m->disable_check();
_m->disable(F_PATH);
_m->disable(F_UPDATE);
_m->disable(DLG_USER);
return TSkeleton_application::create();
}
return error_box("L'utente %s non <20> abilitato all'uso di questo programma", (const char *)user());
}
void TInstaller::main_loop()
{
_m->run();
if (_m->installed() && testdatabase()) // Almeno 1 modulo installato ?
{
// Lancia conversione: ba1 -0 -C -uPRASSI
TExternal_app conversion("ba1 -0 -C");
conversion.run();
}
delete _m;
_m = NULL;
}
class TExtendedInstaller : public TInstaller
{
protected:
virtual bool create();
virtual void main_loop();
};
bool TExtendedInstaller::create()
{
if (!TApplication::test_assistance_year())
{
TExternal_app attivazione("ba1 -4");
attivazione.run();
dongle().login(); // Rilegge anno assistenza
}
_m = new TInstaller_mask() ;
return TSkeleton_application::create();
}
void TExtendedInstaller::main_loop()
{
_m->run();
if (_m->installed() && testdatabase()) // Almeno 1 modulo installato ?
{
// Lancia conversione: ba1 -0 -C -uPRASSI
TExternal_app conversion("ba1 -0 -C");
conversion.run();
}
delete _m;
_m = NULL;
}
#define PROGNAME "Installer"
int ba1700(int argc, char* argv[])
{
if (user() != ::dongle().administrator())
{
TInstaller app;
app.run(argc, argv, PROGNAME);
} else {
TExtendedInstaller app;
app.run(argc, argv, PROGNAME);
}
return 0;
}