//Il sorgente va scritto in notazione ungherese. //Le variabili seguono la seguente regola: 'acronimo tipo'+'nome variabile cammellata' //Es. wxArrayString 'as' + 'AcceptRefuse' -> asAcceptRefuse #include "wxinc.h" #ifdef WIN32 #include #endif #include #include #include "key.h" #include "wizard.h" #include "utils.h" /////////////////////////////////////////////////////////// // CampoFrame /////////////////////////////////////////////////////////// class CampoFrame : public wxFrame { protected: DECLARE_EVENT_TABLE(); virtual void OnErase(wxEraseEvent& e); public: CampoFrame(); }; BEGIN_EVENT_TABLE(CampoFrame, wxFrame) EVT_ERASE_BACKGROUND(CampoFrame::OnErase) END_EVENT_TABLE() void CampoFrame::OnErase(wxEraseEvent& e) { //preparazione background wxDC& dc = *e.GetDC(); const wxRect rect = GetClientSize(); wxColour c0 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); wxColour c1 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); wxColour c2 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW); wxRect rect1 = rect; rect1.SetBottom(rect.GetBottom() / 2); dc.GradientFillLinear(rect1, c0, c1, wxSOUTH); wxRect rect2 = rect; rect2.SetTop(rect.GetBottom() / 2); dc.GradientFillLinear(rect2, c1, c2, wxDOWN); const int nHeight = rect.GetHeight()/10; wxFont* pFont = wxTheFontList->FindOrCreateFont(nHeight, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_BOLD); dc.SetFont(*pFont); dc.SetBackgroundMode(wxTRANSPARENT); const int k = nHeight / 16 + 1; dc.SetTextForeground(c2); dc.DrawText(APPNAME, k, k); dc.SetTextForeground(c1); dc.DrawText(APPNAME, k/2, k/2); int w, h; const wxString strSetup = wxT("Setup"); dc.GetTextExtent(strSetup, &w, &h); dc.SetTextForeground(c2); dc.DrawText(strSetup, rect.GetRight()-w-k/2, rect.GetHeight()-h-k/2); dc.SetTextForeground(c1); dc.DrawText(strSetup, rect.GetRight()-w-k, rect.GetHeight()-h-k); } CampoFrame::CampoFrame() : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0) { ShowFullScreen(true); } /////////////////////////////////////////////////////////// // CampoSetup /////////////////////////////////////////////////////////// //classe principale, ovvero applicazione class CampoSetup : public wxApp { CampoFrame* m_pMainFrame; wxLocale m_locale; wxString m_strSetupPath; CampoWizard* m_pWizard; private: bool WriteRegistryKey(HKEY hBaseKey, const wxString strKey, const wxString& strValue) const; wxString ReadRegistryKey(HKEY hBaseKey, const wxString strKey) const; wxString GetFolderPath(unsigned int uPathID) const; protected: DECLARE_EVENT_TABLE() //metodi principali dell'applicazione void OnTimer(wxTimerEvent& e); void DiskUpdate(); void InternetUpdate(); void ClientUpdate(); void NormalSetup(); bool CampoRunning(const wxString& strAppName, const wxString& strMsg) const; //metodi di interfaccia con Windows bool CreateIcon(unsigned int csidl, const wxFileName& strExeFile, const wxString& strLinkName) const; bool CreateAutostartMode(const int iSrvAutostartMode, const wxString& strPath); void AssociateExtension(const wxFileName& strExeFile, const wxString strExt); //metodi di interfaccia con il registry di Windows wxString ReadRootRegistryKey(const wxString strKey) const; wxString ReadLocalMachineRegistryKey(const wxString strKey) const; bool WriteRootRegistryKey(const wxString strKey, const wxString& strValue) const; bool WriteLocalMachineRegistryKey(const wxString strKey, const wxString& strValue) const; //metodi di utility per i vari modi di aggiornamento const wxString GetSourceDir(const wxString strDirName) const; void EmptyOutDir(const wxString& strDir) const; bool UnzipModule(const wxString& strPrgLocPath, const wxString& strSrc, const wxString& strModule) const; bool CopyFilesAndDirs(const wxString& FilesListI, wxString strFileCurr, const bool bIni) const; void UpdateInstallIni(const wxString strSourcePath, const wxString strDestPath, const wxString& strModule) const; bool HTTPGet(const wxString& strLocalPath, const wxString& strWebPath) const; //metodi di aggiornamento non standard (client, da disco e via web con installazione moduli) int ClientUpdateModule(const wxString& strLocalPath, const wxString& strRemotePath, const wxString strModule) const; bool DiskUpdateModule(const wxString& strLocalPath, const wxString& strWebPath, const wxString strModule) const; bool InternetUpdateModule(const wxString& strLocalPath, const wxString& strWebPath, const wxString strModule) const; public: virtual bool OnInit(); }; IMPLEMENT_APP(CampoSetup) BEGIN_EVENT_TABLE(CampoSetup, wxApp) EVT_TIMER(883, OnTimer) END_EVENT_TABLE() //---------------------------------------------------------------- // Metodi di lettura/scrittura registry di Windows (fantastici!) //---------------------------------------------------------------- wxString CampoSetup::ReadRegistryKey(HKEY hBaseKey, const wxString strKey) const { wxString strValue; HKEY hKey = NULL; wxString strPath, strName; wxFileName::SplitPath(strKey, &strPath, &strName, NULL); bool ok = ::RegOpenKeyEx(hBaseKey, strPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS; if (ok) { BYTE buff[512]; DWORD type = REG_SZ; DWORD dw = sizeof(buff); ok = ::RegQueryValueEx(hKey, strName, NULL, &type, buff, &dw) == ERROR_SUCCESS; if (ok) strValue = buff; ::RegCloseKey(hKey); } return strValue; } wxString CampoSetup::ReadRootRegistryKey(const wxString strKey) const { return ReadRegistryKey(HKEY_CLASSES_ROOT, strKey); } wxString CampoSetup::ReadLocalMachineRegistryKey(const wxString strKey) const { return ReadRegistryKey(HKEY_LOCAL_MACHINE, strKey); } bool CampoSetup::WriteRegistryKey(HKEY hBaseKey, const wxString strKey, const wxString& strValue) const { HKEY hKey = NULL; DWORD dw = 0; //splitta la stringa in path e valore wxString strPath, strName; wxFileName::SplitPath(strKey, &strPath, &strName, NULL); bool ok = ::RegCreateKeyEx(hBaseKey, strPath, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hKey, &dw) == ERROR_SUCCESS; if (ok) { ok = ::RegSetValueEx(hKey, strName, 0, REG_SZ, (BYTE*)(const wxChar*)strValue, DWORD(2*strValue.Len()+2)) == ERROR_SUCCESS; ::RegCloseKey(hKey); } return ok; } bool CampoSetup::WriteRootRegistryKey(const wxString strKey, const wxString& strValue) const { return WriteRegistryKey(HKEY_CLASSES_ROOT, strKey, strValue); } bool CampoSetup::WriteLocalMachineRegistryKey(const wxString strKey, const wxString& strValue) const { return WriteRegistryKey(HKEY_LOCAL_MACHINE, strKey, strValue); } //---------------------------------- // Metodi di interfaccia con Windows //---------------------------------- wxString CampoSetup::GetFolderPath(unsigned int uPathID) const { TCHAR szPath[MAX_PATH] = wxT(""); HRESULT hres = ::SHGetFolderPath(NULL, uPathID, NULL, SHGFP_TYPE_CURRENT, szPath); return szPath; } void CampoSetup::AssociateExtension(const wxFileName& strExeFile, const wxString strExt) { // Register icon and application WriteRootRegistryKey(strExt, APPNAME); wxString str = strExeFile.GetFullPath(); str += wxT(",0"); WriteRootRegistryKey(wxT("Campo\\DefaultIcon"), str); str = strExeFile.GetFullPath(); str += wxT(" \"%1\""); WriteRootRegistryKey(wxT("Campo\\shell\\open\\command"), str); } bool CampoSetup::CreateAutostartMode(const int iSrvAutostartMode, const wxString& strPath) { //creazione dei filenames e dei path necessari in giro per la funzione //filename (con path quindi) di Lurch.exe wxFileName strExe(strPath, wxT("lurch.exe")); strExe.AppendDir("servers"); //stringa path della cartella Servers in base alle scelte dell'utente const wxString strSrvPath = strPath + "\\servers"; switch (iSrvAutostartMode) { //esecuzione server come servizi (magia!) case 0: { //cerca se non esiste per caso gia' da una precedente installazione.. //..non serve piu' a un cazzo ma si e' tenuto come prova in debug di lettura del registry! wxString strValue = ReadLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application"); //elimina un eventuale servizio precedente (senno' col cavolo che lo riesce a modificare!) //utilizza il programma instsrv.exe dentro la cartella servers installata wxString strRemove = strSrvPath + "\\instsrv Lurch REMOVE"; const long lRemove = wxExecute(strRemove, wxEXEC_SYNC); //aggiunge la voce ai servizi di windows (dentro strumenti di amministrazione) //utilizza i programmi instrv.exe e srvany.exe dentro la cartella servers installata wxString strCreateService = strSrvPath + "\\instsrv Lurch "; strCreateService += strSrvPath; strCreateService += "\\srvany.exe"; //esegue il programma di installazione servizi di Windows creando la voce const long lExec = wxExecute(strCreateService, wxEXEC_SYNC); if (lExec >= 0) { //crea le voci nel registry di windows WriteLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application", strExe.GetFullPath()); wxString strExecService = GetFolderPath(CSIDL_SYSTEM); strExecService += "\\NET START Lurch"; //avvia il servizio const long lExecLurch = wxExecute(strExecService, wxEXEC_SYNC); if (lExecLurch < 0) WarningBox("Impossibile eseguire il servizio del gestore applicazioni.\nLanciarlo manualmente dagli strumenti di amministrazione nel pannello di controllo!"); } else WarningBox("Impossibile registrare il servizio per l'esecuzione automatica del gestore applicazioni.\nSelezionare una diversa modalita' di esecuzione!"); } break; //link nella cartella esecuzione automatica case 1: { CreateIcon(CSIDL_COMMON_STARTUP, strExe, "lurch"); } break; default: break; } return true; } bool CampoSetup::CreateIcon(unsigned int csidl, const wxFileName& strExeFile, const wxString& strLinkName) const { //csidl = CSIDL_COMMON_DESKTOPDIRECTORY = desktop //csidl = CSIDL_COMMON_STARTUP = all users esecuzione automatica wxString strDesktopPath = GetFolderPath(csidl); if (!strDesktopPath.IsEmpty()) { CoInitialize(NULL); // Get a pointer to the IShellLink interface. IShellLink* psl; HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); if (SUCCEEDED(hres)) { IPersistFile* ppf; // Set the path to the shortcut target and add the description. psl->SetPath(strExeFile.GetFullPath()); psl->SetWorkingDirectory(strExeFile.GetPath()); psl->SetDescription(APPNAME); // Query IShellLink for the IPersistFile interface for saving the // shortcut in persistent storage. hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); if (SUCCEEDED(hres)) { wxFileName fnLnk; wxString strName = strLinkName + ".lnk"; fnLnk.Assign(strDesktopPath, strName); // Save the link by calling IPersistFile::Save. wxString strPath = fnLnk.GetFullPath(); wchar_t buff[_MAX_PATH]; memset(buff, 0, sizeof(buff)); wxConvLocal.MB2WC(buff, strPath, strPath.Len()); hres = ppf->Save(buff, true); ppf->Release(); } psl->Release(); } CoUninitialize(); } return true; } //---------------------------------------------------------------- // Metodi di utility per i vari tipi di aggiornamento //---------------------------------------------------------------- static int PatchCompare(const wxString& first, const wxString& second) { const wxFileName fn1(first); const wxFileName fn2(second); const wxString strName1 = fn1.GetName().Lower(); const wxString strName2 = fn2.GetName().Lower(); if (strName1 == "syinst1") return -1; if (strName2 == "syinst1") return 1; return strName1.CompareTo(strName2); } const wxString CampoSetup::GetSourceDir(const wxString strDirName) const { wxFileName strSourcePath(m_strSetupPath, "pippo.txt"); strSourcePath.AppendDir(".."); strSourcePath.AppendDir(".."); strSourcePath.AppendDir(strDirName); strSourcePath.MakeAbsolute(); const wxString strSrc = strSourcePath.GetPath(); return strSrc; } //metodo per aggiornare il modulo SY in install.ini void CampoSetup::UpdateInstallIni(const wxString strSourcePath, const wxString strDestPath, const wxString& strModule) const { for (int j = 0; j < 2; j++) { wxString strParagraph = strModule; if (j > 0) strParagraph << j; CampoIniFile InstallIniSource(strSourcePath, strParagraph); CampoIniFile InstallIniDest(strDestPath, strParagraph); wxString strWrk; long nIndex; for (bool ok = InstallIniSource.GetFirstEntry(strWrk, nIndex); ok; ok = InstallIniSource.GetNextEntry(strWrk, nIndex)) { InstallIniDest.Set(strWrk, InstallIniSource.Get(strWrk)); } } } bool CampoSetup::UnzipModule(const wxString& strPrgLocPath, const wxString& strSrc, const wxString& strModule) const { bool ok = false; wxArrayString asFilesList; //..contando anche quanti sono e memorizzandoli in un array asFileList const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asFilesList, strModule+"*.zip"); if (uFilesToCopy > 0) { //ordina le patch per numero crescente ma mette davanti a tutte il pacco (sysinst1) asFilesList.Sort(PatchCompare); for (size_t i = 0; i < uFilesToCopy; i++) { UnzipFile(asFilesList[i] , strPrgLocPath); } //aggiorna l'install.ini in base al numero di patch e versione dell'ultimo file zip di sistema //ci vuole un giro allucinogeno per trasformare il .zip in .ini e togliere quel cazzo di 1 in fondo wxFileName strLastFile(asFilesList[uFilesToCopy - 1]); //zip con path completo wxString strWrk = strLastFile.GetName(); strWrk.Truncate(strWrk.Len() - 1); strLastFile.SetName(strWrk); strLastFile.SetExt("ini"); strWrk = strLastFile.GetFullPath(); //adesso che ha trovato quello sporco ultimo .ini prende versione e patch e le copia nell'install.ini.. //..nella dir dei programmi; lo fa paragrafo x paragrafo ([sy],[sy1]..) //potrebbe sembrare assurdo un for, ma e' per futuri sottomoduli con numero > 1 UpdateInstallIni(strWrk, strPrgLocPath + "/install.ini", "sy"); } return uFilesToCopy > 0; } bool CampoSetup::CopyFilesAndDirs(const wxString& FilesListI, wxString strFileCurr, const bool bIni) const { bool ok = true; strFileCurr.MakeLower(); //minuscolizzazione di sicurezza const wxFileName strFileName(strFileCurr); //i files .ini vanno trattati con i guanti (se esistono gia' non vanno copiati!!!) //parte da eseguire solo in caso sia indicata la trattazione degli ini (bIni true) if (bIni) { if (strFileName.GetExt() == "ini") { const wxString strName = strFileName.GetName(); //campo.ini e install.ini vanno lasciati stare se esistono (aggiornamento)!!! if ((strName == "campo" || strName == "install") && strFileName.FileExists()) ok = false; } } if (ok) { //eventuali sottodirectory le crea (solo se hanno un nome) const wxString strDir = strFileName.GetPath(); if (!strDir.IsEmpty() && !wxDirExists(strDir)) wxMkdir(strDir); if(!wxCopyFile(FilesListI, strFileCurr)) { wxString strErr = "Impossibile copiare il file "; strErr += FilesListI; strErr += " in "; strErr += strFileCurr; strErr += "\nInstallazione interrotta!"; ErrorBox(strErr); ok = false; } } return ok; } //metodo per accoppare tutti i files di una directory void CampoSetup::EmptyOutDir(const wxString& strDir) const { wxArrayString asFilesList; const size_t uFilesToKill = wxDir::GetAllFiles(strDir, &asFilesList, "*.*"); for (size_t i = 0; i < uFilesToKill; i++) ::wxRemoveFile(asFilesList[i]); } //----------------------------------------------------- // METODI BASSO LIVELLO PER AGGIORNAMENTI NON STANDARD //----------------------------------------------------- //---------------------------- // 1) AGGIORNAMENTO CLIENT //---------------------------- //Aggiornatore client. Copia i files del programma da una directory remota su un server campo nella directory... //...locale di campo int CampoSetup::ClientUpdateModule(const wxString& strLocalPath, const wxString& strRemotePath, const wxString strModule) const { int nLocVer, nLocPatch, nRemVer, nRemPatch; { CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strModule); nLocVer = iniLocalInstall.GetInt("Versione"); nLocPatch = iniLocalInstall.GetInt("Patch"); CampoIniFile iniRemoteInstall(strRemotePath + "/install.ini", strModule); nRemVer = iniRemoteInstall.GetInt("Versione"); nRemPatch = iniRemoteInstall.GetInt("Patch"); } int cmp = nLocVer - nRemVer; if (cmp == 0) cmp = nLocPatch - nRemPatch; //il client e' piu' indietro e quindi va aggiornato! if (cmp < 0) { bool bOk = true; wxProgressDialog pi("Aggiornamento elenco files dal server...", "", 100, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); wxArrayString asGroups; { wxString strGroup; long nIndex; CampoIniFile iniRemoteInstall(strRemotePath + "/install.ini", ""); for (bool ok = iniRemoteInstall.GetFirstGroup(strGroup, nIndex); ok; ok = iniRemoteInstall.GetNextGroup(strGroup, nIndex)) { if(strGroup.Len() > 2 && strGroup.StartsWith(strModule)) asGroups.Add(strGroup); } } //controlla tutti i sottomoduli del modulo [sy1],[sy2]... for (size_t i = 0; i < asGroups.GetCount() && bOk; i++) { const wxString& strParagraph = asGroups[i]; CampoIniFile iniRemoteInstallModule(strRemotePath + "/install.ini", strParagraph); //install.ini locale che deve essere aggiornato durante la copia dei files! CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strParagraph); //ogni file dell'elenco del sottomodulo corrente va copiato for (int j = 0;; j++) { pi.Pulse(); //magica barra modello supercar! const wxString strVarName = wxString::Format("File(%d)", j); wxString strCurrFile = iniRemoteInstallModule.Get(strVarName); if (strCurrFile.IsEmpty()) break; strCurrFile = strCurrFile.BeforeFirst('|'); const wxString strSrcPath = strRemotePath + "/" + strCurrFile; const wxString strDstPath = strLocalPath + "/" + strCurrFile; //copia il file remoto di origine sul file locale di destinazione (overwrite=true di default) if (!wxCopyFile(strSrcPath, strDstPath)) { wxString strError = "Impossibile copiare il file "; strError += strSrcPath; strError += " in "; strError += strDstPath; strError += "\nAssicurarsi che il client locale di "; strError += APPNAME; strError += " non sia in funzione.\n"; strError += "Assicurarsi che il server di "; strError += APPNAME; strError += " sia in funzione e raggiungibile in rete.\n"; strError += "Aggiornamento interrotto!"; ErrorBox(strError); bOk = false; break; } //se ci sono zip deve scompattarli (per ora esiste solo res.zip) if (strCurrFile.EndsWith("res.zip")) { UnzipFile(strDstPath, strLocalPath + "/res"); } //se riesce la copia del file aggiorna l'install.ini sul file (se non lo facesse non comparirebbero... //...eventuali nuovi files iniLocalInstall.Set(strVarName, strCurrFile); } //for(int j... //una volta termiata la copia dei files del sottmodulo[i] scatta l'aggiornamento dell'install.ini locale... //...al livello versione/patch appena copiate sempre del sottomodulo[i] iniLocalInstall.Set("Versione", nRemVer); iniLocalInstall.Set("Patch", nRemPatch); } //for(int i... //una volta termiata la copia dei files dell'intero modulo scatta l'aggiornamento dell'install.ini locale al.. //..livello versione/patch appena copiate CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strModule); iniLocalInstall.Set("Versione", nRemVer); iniLocalInstall.Set("Patch", nRemPatch); } //if(cmp<0... return cmp; } //---------------------------- // 2) AGGIORNAMENTO DA DISCO //---------------------------- //Aggiornatore da disco. Copia i files delle patch da una directory su disco in una directory di appoggio... //...temporanea dove esegue lo scompattamento con destinazione la directory locale bool CampoSetup::DiskUpdateModule(const wxString& strLocalPath, const wxString& strDiskPath, const wxString strModule) const { //puo' chiamare direttamente il metodo che scompatta tutte le patch del modulo a partire dal pacco iniziale... //...fino all'ultima;il metodo le ordina gia' in modo crescente di numero d'ordine return UnzipModule(strLocalPath, strDiskPath, strModule); } //------------------------------- // 3) AGGIORNAMENTO DA INTERNET //------------------------------- bool CampoSetup::HTTPGet(const wxString& strLocalPath, const wxString& strWebPath) const { wxString strServer, strPath; int nSlash = strWebPath.First('/'); strServer = strWebPath.Left(nSlash); strPath = strWebPath.Mid(nSlash); wxHTTP http; //connessione al server web con le patch if (http.Connect(strServer)) { wxInputStream* pStream = http.GetInputStream(strPath); if (pStream != NULL) { //compila un file di testo temporaneo con l'elenco dei files che trova sul server wxFileOutputStream fos(strLocalPath); fos.Write(*pStream); delete pStream; return true; } } return false; } //Aggiornatore via web. Copia i files delle patch da una directory web remota in una directory di appoggio... //...temporanea dove esegue lo scompattamento con destinazione la directory locale bool CampoSetup::InternetUpdateModule(const wxString& strLocalPath, const wxString& strWebPath, const wxString strModule) const { bool ok = false; int nLocVer, nLocPatch; { CampoIniFile iniLocalInstall(strLocalPath + "/install.ini", strModule); nLocVer = iniLocalInstall.GetInt("Versione"); nLocPatch = iniLocalInstall.GetInt("Patch"); } //Svuota,elimina e ricrea una directory temporanea di appoggio ove mettere i files delle patch da scompattare //E' necessaria questa operazione per non trovarsi ancora files di vecchie patch parcheggiati nella dir! const wxString strTempDir = wxFileName::GetTempDir() + "/setup/"; EmptyOutDir(strTempDir); //deve svuotare la directory dai files per poterla eliminare!!! if (::wxRmdir(strTempDir)) //elimina la dir adesso vuota ::wxMkDir(strTempDir); //la ricrea const wxString strTempFile = strTempDir + "httpdir.txt"; if (HTTPGet(strTempFile, strWebPath)) { //partendo dal file temporaneo ne compila un secondo con i soli nomi dei file validi da scaricare //i criteri di selezione sono il nome del modulo ed il livello patch wxTextFile tfFilesList; if (tfFilesList.Open((strTempFile))) { wxProgressDialog pi("Aggiornamento elenco files dal server...", "", (int)tfFilesList.GetLineCount(), NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); for (wxString strWrk = tfFilesList.GetFirstLine(); !tfFilesList.Eof(); strWrk = tfFilesList.GetNextLine()) { int nPos = strWrk.Find("href"); if (nPos > 0) { wxString strHref = strWrk.Mid(nPos + 5, 16); strHref = strHref.AfterFirst('"'); strHref = strHref.BeforeLast('"'); if ( strHref.StartsWith(strModule) && ((atoi(strHref.Mid(2)) > nLocPatch) || (nLocPatch == 0))) { if (!pi.Update((int)tfFilesList.GetCurrentLine(), strHref)) break; HTTPGet(strTempDir+strHref, strWebPath+strHref); } } } //chiude il file temporaneo tfFilesList.Close(); } //if(tfFilesList... //scompatta le patch di sistema e aggiorna l'install.ini locale ok = UnzipModule(strLocalPath, strTempDir, strModule); } //if(HTTPGet(... return ok; } //----------------------------------------------------- // METODI ALTO LIVELLO PER AGGIORNAMENTI NON STANDARD //----------------------------------------------------- //--------------------------------------------------------------- // 1) metodo per l'aggiornamento dei client di rete in automatico //--------------------------------------------------------------- void CampoSetup::ClientUpdate() { wxFileName fn(m_strSetupPath, "install.ini"); fn.AppendDir(".."); fn.MakeAbsolute(); const wxString strLocalPath = fn.GetPath(); wxString strRemotePath; { CampoIniFile iniLocalInstall(fn.GetFullPath(), "Main"); strRemotePath = iniLocalInstall.Get("DiskPath"); } ClientUpdateModule(strLocalPath, strRemotePath, "sy"); wxSetWorkingDirectory(strLocalPath); wxExecute("ba1 -6 /uADMIN"); } //----------------------------------------------------------------------------------------------- // 2) metodo per l'aggiornamento da disco attraverso il menu di Manutenzione/Installazione moduli //----------------------------------------------------------------------------------------------- void CampoSetup::DiskUpdate() { wxFileName fn(m_strSetupPath, "install.ini"); fn.AppendDir(".."); fn.MakeAbsolute(); const wxString strLocalPath = fn.GetPath(); wxString strRemotePath; { CampoIniFile iniLocalInstall(fn.GetFullPath(), "Main"); strRemotePath = iniLocalInstall.Get("DiskPath"); } DiskUpdateModule(strLocalPath, strRemotePath, "sy"); wxSetWorkingDirectory(strLocalPath); wxExecute("ba1 -6 /uADMIN"); } //---------------------------------------------------------------------------------------- // 3) metodo per l'aggiornamento via internet attraverso Manutenzione/Installazione moduli //---------------------------------------------------------------------------------------- void CampoSetup::InternetUpdate() { //install.ini locale dove setup.exe e' in esecuzione wxFileName fn(m_strSetupPath, "install.ini"); fn.AppendDir(".."); fn.MakeAbsolute(); const wxString strLocalPath = fn.GetPath(); //quale e' il path web da cui aggiornarmi? wxString strRemotePath; { //Install.ini locale da cui leggere il path di dove sta il mio server web CampoIniFile iniLocalInstall(fn.GetFullPath(), "Main"); strRemotePath = iniLocalInstall.Get("WebPath"); } //aggiornamento del modulo SY via web InternetUpdateModule(strLocalPath, strRemotePath, "sy"); //lanciare ba1.exe -6 in uscita wxSetWorkingDirectory(strLocalPath); wxExecute("ba1 -6 /uADMIN"); } //-------------------------------------------------------------------------- //metodo per tutte le installazioni e gli aggiornamenti automatici in locale //-------------------------------------------------------------------------- void CampoSetup::NormalSetup() { m_pWizard = new CampoWizard(m_pMainFrame); if (m_pWizard->Run()) { //e' una DEMO o una versione normale? const bool bInstallDemoVersion = m_pWizard->GetInstDemoVersion(); // 0) INSTALLAZIONE VERSIONE DEMO (SIETE PAZZI?) //---------------------------------------------- if (bInstallDemoVersion) { const wxString& strPrgLocPath = "c:/campodemo"; const wxString& strDataPath = strPrgLocPath + "/dati"; const wxString& strHelpPath = strPrgLocPath + "/htmlhelp"; //creazione delle directories necessarie alla installazione DEMO CheckAndMakeDir(strPrgLocPath, "programmi"); CheckAndMakeDir(strDataPath, "dati"); CheckAndMakeDir(strHelpPath, "help"); //copia della campodemo sull'hard disk in c:\campodemo wxArrayString asDemoList; const wxString strSrc = GetSourceDir("campodemo"); const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asDemoList); wxString strFileCurr; const size_t nPathLenght = strSrc.Len(); wxProgressDialog pi("Installazione Versione Demo...", "", (int)uFilesToCopy, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); for (size_t i = 0; i < uFilesToCopy; i++) { if (!pi.Update((int)i, asDemoList[i])) break; asDemoList[i].Lower(); strFileCurr = strPrgLocPath; strFileCurr += asDemoList[i].Mid(nPathLenght); if (!strFileCurr.IsEmpty()) { if (!CopyFilesAndDirs(asDemoList[i], strFileCurr, false)) break; } } //icona sul desktop const bool bDesktopShortcut = m_pWizard->GetDesktopShortcut(); if (bDesktopShortcut) { const wxFileName strExe("c:/campodemo", wxT("ba0.exe")); CreateIcon(CSIDL_COMMON_DESKTOPDIRECTORY, strExe, "CampoDEMO"); } //lanciare ba0.exe in uscita wxSetWorkingDirectory(strPrgLocPath); wxExecute("ba0"); } else //tutti i casi normali (std,server,client,aggiornamento) { // 1) RACCOLTA PARAMETRI GENERALI INSTALLAZIONE (tipo,path,cartelle,servers,...) //------------------------------------------------------------------------------ //tipo di installazione/aggiornamento const InstallationType uInstallationType = m_pWizard->GetInstallationType(); const bool bNewInstallation = uInstallationType != it_upgrade; //installazione servers? solo per server di campo const bool bInstallLurch = uInstallationType == it_server && (m_pWizard->GetInstUseAuth() || m_pWizard->GetInstUseDict()); //uso servers? sarebbe solo per i client ma lo teniamo buono per tutti const bool bUseLurch = uInstallationType != it_server && (!m_pWizard->GetSrvAuth().IsEmpty() || !m_pWizard->GetSrvDict().IsEmpty()); //installazione datidemo? (oddio speriamo di no!; comunque vale solo per installazione standard) const bool bInstallDemoData = uInstallationType == it_standalone && m_pWizard->GetInstDemoData(); //cartelle selezionate dall'utente const wxString& strPrgLocPath = m_pWizard->GetPrgLocPath(); const wxString& strDataPath = m_pWizard->GetDataPath(); //se nuova installazione deve anche creare la directory di destinazione if (bNewInstallation) { //creazione della directory dei programmi (compreso l'intero albero directory) CheckAndMakeDir(strPrgLocPath, "programmi"); //creazione della directory dei dati (compreso l'intero albero directory) CheckAndMakeDir(strDataPath, "dati"); } // 2) COPIA DEI FILES DI INSTALLAZIONE DALLA CARTELLA CAMPO (E SUBDIRS) (SU CD) ALLA CARTELLA DESTINAZIONE //-------------------------------------------------------------------------------------------------------- //copia del contenuto della cartella campo nella cartella di destinazione (installaz/aggiornam) //per prima cosa cerca la cartella dei files sorgente... wxArrayString asFilesList; wxFileName strSourcePath(m_strSetupPath, "*.*"); strSourcePath.AppendDir(".."); strSourcePath.MakeAbsolute(); //stringa inutile al programma ma decisiva per il programmatore const wxString strSrc = strSourcePath.GetPath(); //..contando anche quanti sono e memorizzandoli in un array asFileList const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asFilesList); const size_t nPathLenght = strSrc.Len(); //progress bar wxProgressDialog pi("Installazione Dati e Programmi di base...", "", (int)uFilesToCopy, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); for (size_t i = 0; i < uFilesToCopy; i++) { //per ogni file da copiare controlla i path sorgente e destinazione(problema con sottodirectory tipo.. //..dati); strFileCurr va lasciato qui perche' DEVE ESSERE AZZERATO ad ogni cambio file!!!!!! wxString strFileCurr; //controlla se il file corrente e' dentro una sottodirectory (tipo dati,servers,setup...) oppure e' al.. //..primo livello (quindi e' un file di programma) wxString strSourceFile = asFilesList[i].Lower(); strSourceFile.Replace("\\", "/"); //e' in una subdir se la lunghezza del suo path prima dell'ultimo '/' e' > della lunghezza del path di root const bool bIsSubDir = strSourceFile.Find('/', true) > (int)nPathLenght; //2A) files con subdirectory if (bIsSubDir) { //files dei dati standard! solo in caso di nuova installazione!! if (strSourceFile.Find("/dati/") > 0) { //i DATI NON VANNO MAI installati in caso di aggiornamento!!! //e nemmeno in caso si scelga di installare i dati demo (senno' sporca la dir dati e i datidemo non si installano) //Ricordare che c'e' gia' stato il controllo nella Forward della pagina di selezione, quindi la cartella.. //..di destinazione e' comunque vuota if (bNewInstallation && !bInstallDemoData) { strFileCurr = strDataPath; strFileCurr += asFilesList[i].Mid(nPathLenght + 5); } } else if (strSourceFile.Find("/servers/") > 0) //che fare con i servers? copiare la directory... { if (bInstallLurch) //..ma solo se devi installare i servers { strFileCurr = strPrgLocPath; strFileCurr += "/servers"; strFileCurr += asFilesList[i].Mid(nPathLenght + 8); } } else //files vari di altre subdirectory che si installano sempre (es. setup) { strFileCurr = strPrgLocPath; strFileCurr += asFilesList[i].Mid(nPathLenght); } } //2B) files senza subdirectory (programmi!) else { strFileCurr = strPrgLocPath; strFileCurr += asFilesList[i].Mid(nPathLenght); } //copia i files nella cartella di destinazione (programmi,dati,cazzi e mazzi);se il nome del file.. //..di destinazione e' vuoto significa che non lo deve copiare!! (es. dati in aggiornamento) if (!strFileCurr.IsEmpty()) { //aggiorna la progind if (!pi.Update((int)i, asFilesList[i])) break; //eventuali sottodirectory le crea (solo se hanno un nome) e poi copia fisicamente i files //se un file non si copia interrompe l'installazione con un ErrorBox if (!CopyFilesAndDirs(asFilesList[i], strFileCurr, true)) break; } //if (!strFileCurr.IsEmpty().. } //for(size_t... UpdateInstallIni(strSrc + "/install.ini", strPrgLocPath + "/install.ini", "sy"); // 3) INSTALLAZIONE DATI DEMO //--------------------------- //installazione dei dati dimostrativi (che schifo!).Non si puo' fare in aggiornamento! /* if (bInstallDemoData && uInstallationType < 3) { //trova la cartella datidemo da copiare wxArrayString asDataList; const wxString strSrc = GetSourceDir("datidemo"); //conta i files da copiare e si lancia nell'operazione di copiatura... //Vale quanto detto per l'installazione dell'area dati const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asDataList); wxString strFileCurr; const size_t nPathLenght = strSrc.Len(); wxProgressDialog pi("Installazione Dati Demo...", "", (int)uFilesToCopy, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); for (size_t i = 0; i < uFilesToCopy; i++) { if (!pi.Update((int)i, asDataList[i])) break; asDataList[i].Lower(); strFileCurr = strDataPath; strFileCurr += asDataList[i].Mid(nPathLenght); if (!strFileCurr.IsEmpty()) { //eventuali sottodirectory le crea (solo se hanno un nome) e poi copia fisicamente i files //se un file non si copia interrompe l'installazione con un ErrorBox if (!CopyFilesAndDirs(asDataList[i], strFileCurr, false)) break; } //if (!strFileCurr.IsEmpty().. } //for (size_t i = 0... } //if(bInstallDemoData... */ // 4) COMPILAZIONE CAMPO.INI CON CONFIGURAZIONE NUOVA INSTALLAZIONE //----------------------------------------------------------------- //adesso deve compilare il campo.ini se nuova installazione.. if (bNewInstallation) { { //parentesi necessaria per la scrittura immediata (non cancellare! serve per debug) //paragrafo [Main] CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main"); const unsigned int uDongleType = m_pWizard->GetDongleType(); CampoIniMain.Set("Donglehw", uDongleType); CampoIniMain.Set("Study", strDataPath); CampoIniMain.Set("Firm", "com"); //client o non client? //(attenzione che in Campo e' Std=1 Srv=2 Cli=3) CampoIniMain.Set("Type", uInstallationType); } //paragrafo [Server] if (bInstallLurch || bUseLurch) { CampoIniFile CampoIniSrv(strPrgLocPath + "/campo.ini", "Server"); CampoIniSrv.Set("Dongle", m_pWizard->GetSrvAuth()); CampoIniSrv.Set("Dictionary", m_pWizard->GetSrvDict()); } } //if(bNewInstallation... else //e' un aggiornamento! scrive il type { CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main"); //SOLO se sta aggiornando una versione antecedente alla 10.0 scrive la variabile Type nel campo.ini.. //..ovvero deve testare se Type = 0 if (CampoIniMain.GetInt("Type") == 0) CampoIniMain.Set("Type", CampoIniMain.GetInstallationType()); } // 5) COMPILAZIONE\AGGIORNAMENTO INSTALL.INI CON DISKPATH //------------------------------------------------------- //..e modificare comunque l'install.ini aggiornando eventualmente l'origine dei programmi //parentesi necessaria per la scrittura immediata (non cancellare! serve per debug) { CampoIniFile CampoInstall(strPrgLocPath + "/install.ini", "Main"); if (uInstallationType == it_client) //client: directory origine sul server CampoInstall.Set("DiskPath", m_pWizard->GetPrgNetPath()); else //e' il path assoluto dell'install.ini che sta in 'program' (es. D:\program) { const wxString strSrc = GetSourceDir("program"); CampoInstall.Set("DiskPath", strSrc); } } // 6) CREAZIONE AUTOSTART DEI SERVERS (SE CI SONO) //------------------------------------------------ //solo se sta installando campo in postazione server e deve installare un gestore di servizi.. //..avvia la procedura della creazione dell'autostart(un casino) const int iSrvAutostartMode = m_pWizard->GetSrvAutostartMode(); if (iSrvAutostartMode != lm_none) { CreateAutostartMode(iSrvAutostartMode, strPrgLocPath); } // 7) AGGIORNAMENTO DEL MODULO SY CON EVENTUALI PATCH PRESENTI IN PROGRAM DEL CD E AGGIORNAMENTO INSTALL.INI //---------------------------------------------------------------------------------------------------------- //procede poi al caricamento delle patch eventuali di sistema all'interno della dir 'program' e al.. //..conseguente riaggiornamento del livello versione/patch del SY in install.ini const wxString strPrgCDPath = GetSourceDir("program"); UnzipModule(strPrgLocPath, strPrgCDPath, "sy"); // 8) CREAZIONE DELL'ICONA SUL DESKTOP //------------------------------------ const bool bDesktopShortcut = m_pWizard->GetDesktopShortcut(); if (bDesktopShortcut) { const wxFileName strExe(strPrgLocPath, wxT("ba0.exe")); wxString strLnk; CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main"); InstallationType nInstType = CampoIniMain.GetInstallationType(); switch (nInstType) { case it_server: strLnk = "Campo (Server)"; break; case it_client: strLnk = "Campo (Client)"; break; default: strLnk = "Campo"; break; } //crea comunque l'icona CreateIcon(CSIDL_COMMON_DESKTOPDIRECTORY, strExe, strLnk); } // 9) AGGIORNAMENTO CAMPO.STP //--------------------------- if (bNewInstallation) { //deve aggiungere la nuova installazione al campo.stp for (int i = 1;; i++) { wxString strGroup; strGroup << i; CampoIniFile CampoStp("C:\\campo.stp", strGroup); wxString strPath = CampoStp.Get("Program"); if (strPath.IsEmpty()) { CampoStp.Set("Program", strPrgLocPath); break; } } } // 10) CHIUDE IL SETUP LANCIANDO BA1 -6 PER INSTALLAZIONE MODULI //------------------------------------------------------------- //lanciare ba1.exe -6 in uscita if (wxSetWorkingDirectory(strPrgLocPath)) wxExecute("ba1 -6 /uADMIN"); else ErrorBox("Impossibile installare i moduli. Cartella di destinazione irraggiungibile!"); } } //if (m_pWizard->Run())... m_pWizard->Destroy(); } bool CampoSetup::CampoRunning(const wxString& strAppName, const wxString& strMsg) const { wxSingleInstanceChecker sicProgram(strAppName); int i; for (i = 3; i > 0 && sicProgram.IsAnotherRunning(); i--) wxSleep(1); if (i <= 0) ErrorBox(strMsg); return i <= 0; } //metodo principale che sceglie la modalita' di lancio del programma void CampoSetup::OnTimer(wxTimerEvent& WXUNUSED(e)) { //controllo di eventuali Campo o servers attivi e conseguente interruzione dell'installazione if (CampoRunning("ba0", "Uscire dal programma CAMPO prima di procedere con l'aggiornamento/installazione!") || CampoRunning("ba1", "Uscire dal programma di manutenzione di CAMPO\n prima di procedere con l'aggiornamento/installazione!") || CampoRunning("Authorization", "Spegnere il server di autorizzazioni per poter aggiornare/installare il programma CAMPO!")) { m_pMainFrame->Destroy(); return; } //panegirico all'apparenza inutile ma in realta' decisivo per reperire i veri path assoluti dove funzionano... //..setup, ba0, ba1. NON cancellare!!! wxString strIni = "install.ini"; wxFileName strPath; if (wxFileName::FileExists(strIni)) { strPath = "setup"; } else { strIni.insert(0, "../"); if (wxFileName::FileExists(strIni)) strPath = "."; else { m_pMainFrame->Destroy(); return; } } strPath.MakeAbsolute(); strPath.SetCwd(); //path del programma setup.exe in esecuzione; serve in seguito in quanto alcuni metodi (tipo la GetAllFiles).. //..fanno perdere questo path m_strSetupPath = strPath.GetPath(); wxString strCommand = argv[1]; if (strCommand.IsEmpty()) NormalSetup(); else { if (strCommand == "-ud") DiskUpdate(); if (strCommand == "-uc") ClientUpdate(); if (strCommand == "-uw") InternetUpdate(); } //finestrina x chiudere a mano il programma (sconsigliata causa lancio ba1.exe) // ::wxMessageBox(wxT("Installazione terminata"), APPNAME, wxOK | wxICON_INFORMATION); m_pMainFrame->Destroy(); } bool CampoSetup::OnInit() { wxInitAllImageHandlers(); m_locale.Init(); m_pMainFrame = new CampoFrame; SetTopWindow(m_pMainFrame); wxTimerEvent e(883); AddPendingEvent(e); return true; }