campo-sirio/ba/ba1700.cpp
guy 551ad587e5 Patch level : 2.0 614
Files correlati     : ba1.exe
Ricompilazione Demo : [ ]
Commento            :

AO20113
In fase di installazione moduli su un client con "Installazione di rete
con programmi su disco locale" non viene creata la cartella HTMLHELP,
su ogni modulo viene pertanto restituito l'errore:
"Impossibile creare il file htmlhelp\XXhelp.zip per copiare il file F:\Campo32\htmlhelp\XXhelp.zip"
dove la XX sta ad indicare il modulo in questione ed F:\ è il percorso del server.
Sul server nell'installazione standard invece è tutto corretto.

AO20114
In fase di installazione moduli su un client con "Installazione di rete con
programmi su disco locale" non vengono "unzippati" i files necessari per
l'installazione dell'Help On-Line e non vengono nemmeno create le cartelle
dentro le quali scompattare questi files (ba, ve, cg, ecc…); nonostante la
segnalazione AO20113 ho potuto verificare questa cosa creando a mano,
in fase di installazione, la cartella HTMLHELP e la cartella HTMLHELP\BA.
L'unica cosa che viene riportata dal server sono i files .ZIP dell'help di
ogni modulo.


git-svn-id: svn://10.65.10.50/trunk@11530 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-10-24 07:45:38 +00:00

1422 lines
38 KiB
C++
Executable File
Raw Blame History

#include <stdio.h>
#include <cfiles.h>
#include <agasys.h>
#include <applicat.h>
#include <defmask.h>
#include <dongle.h>
#include <execp.h>
#include <isamrpc.h>
#include <modaut.h>
#include <progind.h>
#include <sheet.h>
#include <utility.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
#define C_BASEPATCH 10
#ifdef _DEMO_
const char* const http_default_path = "/aga/demo/zip/";
#else
const char* const http_default_path = "/aga/program/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;
bool _installed; // Flag per verificare se almeno un modulo e' stato installato
enum { NONE = 0, NEW_MENU = 1, NEW_MENUPRG = 2, NEW_INSTALLER = 4, NEW_DLL = 8 };
int _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;
bool has_module(int modnumber) const;
bool is_zip_file(const TFilename& n) 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();
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_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);
bool run_ba0close() const { return _reboot_program >= NEW_MENUPRG; }
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;
}
bool TInstaller_mask::has_module(int modnumber) const
{
if (modnumber == SRAUT)
{
char s[16];
if (CGetCampoStpValue("Servers", s, sizeof(s)))
return atoi(s) > 0;
}
return main_app().has_module(modnumber,CHK_DONGLE);
}
int TInstaller_mask::precheck_modules(bool only_newer)
{
TString16 release,currrelease;
int patchlevel,modnumber,currpatch;
TString_array& array = rows_array();
FOR_EACH_ARRAY_ROW_BACK(array, r, row)
{
TToken_string& rigar = *row;
release = rigar.get(C_RELEASE);
patchlevel = rigar.get_int(C_PATCH);
currrelease = rigar.get(C_CURRRELEASE);
currpatch = rigar.get_int(C_CURRPATCH);
modnumber=get_module_number(rigar.get(C_CODE));
if (modnumber >= 0 &&
!release.blank() &&
((release > currrelease) ||
(release == currrelease
&& (only_newer ? patchlevel>currpatch: patchlevel>=currpatch) ))
&& has_module(modnumber) )
{
// checca il modulo o la patch se ho installata la stessa versione
const bool chk = rigar.get_char(C_ISPATCH) != 'X' || release == currrelease;
check(r,chk );
}
}
force_update(); // Indispensabile per vedere le righe aggiornate
return items();
}
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 (scanner.token().starts_with(module))
{ 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);
make_dir(path);
ininame = path;
ininame.add(TInstall_ini::default_name());
if (ininame.exist() && yesno_box(TR("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,TR("Connessione al server HTTP..."),FALSE,FALSE);
httpresult=http_get(http_server, remote_ini, ininame);
}
}
}
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();
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
{
TFilename mod_ini = ininame.path();
mod_ini.add(module);
mod_ini << "inst.ini";
if (mod_ini.exist())
{
TInstall_ini moduleini(mod_ini);
add_module(moduleini, 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(FR("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, TR("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
if (*row.get(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
}
row.add(patch, C_PATCH); // aggiorna il patchlevel mostrato per il modulo
}
}
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.blank())
{
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)
{
TInstall_ini curini;
if (curini.demo() != ini.demo())
{
TString msg;
msg << TR("Attenzione: Non e' possibile installare la versione ");
msg << (ini.demo() ? TR("dimostrativa") : TR("normale"));
msg << TR(" nella cartella della versione ");
msg << (curini.demo() ? TR("dimostrativa") : TR("normale"));
return error_box(msg);
}
const TString& version = ini.version(module);
const word year = version2year(version);
if (year < 1997)
return error_box(FR("Il modulo '%s' non ha una versione valida."), module);
#ifndef _DEMO_
if (year > dongle().year_assist())
return error_box(FR("Per installare la versione %s del modulo '%s'\noccorre 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.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;
return underscore;
}
bool TInstaller_mask::is_zip_file(const TFilename& n) const
{
const char* ext = n.ext();
return xvt_str_compare_ignoring_case(ext, "zip") == 0;
}
void TInstaller_mask::create_dirs(const char* path) const
{
TToken_string dirs(path, SLASH);
if (SLASH == '\\')
dirs.replace('/', SLASH);
else
dirs.replace('\\', SLASH);
// 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 << SLASH;
if (!subdir.exist() )
// build destination directory
make_dir(subdir);
}
}
// 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_MENU && dst.exist())
{
dest.rtrim(1);
dest << '_';
}
if (!dest.exist())
create_dirs(dest.path());
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, filesize) == 0)
return error_box(TR("Lo spazio sull'unita' di destinazione e' insufficiente"));
const bool write_ok = ::fcopy(src, dest);
if (write_ok && is_zip)
aga_unzip(src, dest.path());
if (write_ok)
::remove(src);
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)
::remove(src);
}
return ok;
}
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;
}
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 = 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(FR("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 = TR("Decompressione");
if (is_a_patch)
msg << TR(" della patch ") << patchlevel ;
msg << TR(" del modulo '") << module << TR("' in corso...");
TProgind pi(dischi, msg, FALSE, TRUE);
TFilename tempdir; tempdir.tempdir();
// File tottale dei vari sotto-zip
TFilename totti = tempdir; totti.add(module); totti.ext("zip");
for (int d = 1; d <= dischi && ok; d++)
{
TFilename chunk = path;
chunk.add(module);
if (patchlevel > 0)
{
TString16 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);
}
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*)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
pi.addstatus(1);
}
}
aga_unzip(totti, tempdir); // Scompatta il file totale
::remove(totti);
// ***************
// trasferimento
if (ok)
{
// si assicura che sia leggibile il .ini del primo disco
do
{
TFilename cmdline = path;
cmdline.add(ininame.name());
ok = cmdline.exist();
if (!ok)
{
if (askdisk(path,cmdline,1,dischi,(const char*)ini->get("Descrizione"))==K_QUIT)
break;
ok = fexist(cmdline);
if (!ok)
message_box(FR("Impossibile trovare %s\n"),(const char*)cmdline);
else
{
delete ini;
ini = new TInstall_ini (cmdline);
}
}
} while (!ok);
if (ok)
{
msg.cut(0);
msg << TR("Aggiornamento del modulo '") << module << TR("' in corso...");
pi.set_text(msg);
ok = move_module(module, *ini, TRUE);
if (ok)
{
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) //rimozione files da eliminare indicati nel .ini
{
TString killmod;
killmod << module << 99;
if (ini->set_paragraph(killmod))
{
TToken_string rigaini;
TFilename filetokill;
for (int k=0; ;k++)
{
rigaini = ini->get("Kill", NULL, k, "");
if (rigaini.empty())
break;
filetokill = rigaini.get(0);
::remove(filetokill);
}
}
}
}
}
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) << TR("Copia del modulo ") << module;
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);
const int reboot = needs_reboot(dst);
if (reboot > NEW_MENU && dst.exist())
{
dst.rtrim(1);
dst << '_';
}
if (!dst.exist())
create_dirs(dst.path());
ok = ::fcopy(src, dst);
if (ok && is_zip_file(src))
aga_unzip(src, dst.path());
if (ok && reboot != NONE)
_reboot_program |= reboot;
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(TR("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(FR("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(FR("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(FR("Si desidera ritornare alla versione %s.%d del modulo '%s' ?\nAttenzione: non e' garantito il corretto\nfunzionamento 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(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
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)
{
const int basepatch = row->get_int(C_BASEPATCH);
if (oldpatch >= basepatch)
is_patch = !noyes_box(FR("Si desidera reinstallare l'intero modulo '%s'?"
"\nRispondendo NO verranno installate le sole patch"),
(const char *)modulo);
else
is_patch = FALSE; // Quando la versione installata precede la patch base devo reinstallare il 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 *)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(TR("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(TR("Selezionare uno o 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(TR("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, TR("Installazione"),
HR("@1|Modulo@30|Cod.@3|Versione da\ninstallare@11|Liv.\nPatch@6|Data\nRilascio@10|Versione\nInstallata@10|Liv.\nPatch@6|Data\nInstallazione@13|Aggiornamento|Patch Base"),
0x18, 3)
{
_curr_mask = this;
_installed = FALSE;
_reboot_program= NONE;
add_string(F_PATH, 0, PR("Installa da "), 1, 1, 80, "", 60);
add_string(F_CURPATH, 0, PR("Installa in "), 1, 2, 80, "D", 60);
add_button(F_UPDATE, BR("Rileggi", 9), '\0');
add_button(F_INSTALL, BR("Installa", 9), '\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);
TInstall_ini ini;
TFilename path = ini.get("DiskPath");
set(F_PATH, path);
const bool floppy = xvt_fsys_is_removable_drive(path) != 0;
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;
if (_reboot_program != NONE)
{
TString msg;
msg << TR("Sono stati aggiornati i seguenti elementi:") < '\n';
if (_reboot_program & NEW_MENU)
msg << TR("voci di menu;");
if (_reboot_program & NEW_MENUPRG)
msg << TR("navigatore dei menu;");
if (_reboot_program & NEW_INSTALLER)
msg << TR("installatore");
if (_reboot_program & NEW_DLL)
msg << TR("librerie di base;");
msg.rtrim(1);
msg << '\n' << TR("E' 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, "Main");
return ini.get("TestDatabase","Main",-1,"Y") != "N";
}
bool TInstaller::testprograms() const
{
TConfig ini(CONFIG_INSTALL, "Main");
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
}
else
update_dninst(FALSE); // Aggiorna se necessario
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(FR("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
}
else
update_dninst(FALSE); // Aggiorna se necessario
_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();
}
const bool reboot = _m->run_ba0close();
delete _m; _m = NULL;
/*
// TBI: Aggiungere test && non sono lanciato da BA0 (oppure sono lanciato da intall.exe)
if (reboot)
{
TExternal_app ba0close("ba0close.exe");
ba0close.run(TRUE,TRUE,TRUE); // run asynchronous...
}
*/
}
int ba1700(int argc, char* argv[])
{
const char* const PROGNAME = "Installazione moduli";
if (user() != ::dongle().administrator())
{
TInstaller app;
app.run(argc, argv, PROGNAME);
}
else
{
TExtendedInstaller app;
app.run(argc, argv, PROGNAME);
}
return 0;
}