//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"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#ifdef WIN32
#include 
#endif
extern "C"        
{
#include "../xvaga/hlapi_c.h"
#include "../xvaga/skeylink.h"
}
#define HGAP 4
#define VGAP 2
///////////////////////////////////////////////////////////
// Utilities
///////////////////////////////////////////////////////////
bool ErrorBox(const wxString str)
{
  wxMessageBox(str, APPNAME, wxOK | wxICON_ERROR);
  return false;
}
bool WarningBox(const wxString str)
{
  wxMessageBox(str, APPNAME, wxOK | wxICON_EXCLAMATION);
  return false;
}
wxString GetDefaultDestination()
{
  wxString strDest;
//scelta della directory di installazione di default
#ifdef WIN32
  TCHAR strFolder[MAX_PATH];
  ::SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, strFolder);
  strDest = strFolder;
#endif
  if (strDest.IsEmpty())
  {
    // Forse è la cartella base dove è installato Word?
    wxFileType* pDoc = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("doc"));
    if (pDoc != NULL)
    {
      wxFileName strFilename = pDoc->GetOpenCommand(wxT("pippo.doc"));
      while (strFilename.GetDirCount() > 1)
        strFilename.RemoveLastDir();
      strDest = strFilename.GetPath().After('"');
      if (strDest.StartsWith(wxT("C\\")))
        strDest = wxT("C:") + strDest.Mid(1);
    }
  }
  return strDest;
}
class CampoDirCopier : public wxDirTraverser
{
  wxString m_strSrc, m_strDst;
protected:
  virtual wxDirTraverseResult OnDir(const wxString& dirname);
  virtual wxDirTraverseResult OnFile(const wxString& filename);
public:
  void RenameDLL(const wxString& strDLL, bool bOpenGL) const;
  bool Copy(const wxString& src, const wxString& dst, bool bOpenGL);
};
wxDirTraverseResult CampoDirCopier::OnDir(const wxString& dirname)
{ 
  return wxDIR_CONTINUE; 
}
wxDirTraverseResult CampoDirCopier::OnFile(const wxString& filename)
{
  wxFileName strSource(filename);
  strSource.MakeRelativeTo(m_strSrc);
  
  wxString str = m_strDst;
  str += strSource.GetPathSeparator();
  str += strSource.GetFullPath();
  
  wxFileName strDest(str);
  if (!strDest.DirExists())
    strDest.Mkdir();
  ::wxCopyFile(filename, str);
  
  return wxDIR_CONTINUE;
}
void CampoDirCopier::RenameDLL(const wxString& strDLL, bool bOpenGL) const
{
  wxFileName file1(m_strDst, strDLL);
  file1.SetExt(bOpenGL ? wxT("dll") : wxT("old"));
  
  if (file1.FileExists())
  {
    wxFileName file2(file1);
    file2.SetExt(bOpenGL ? wxT("old") : wxT("dll"));
    wxRename(file1.GetFullPath(), file2.GetFullPath());
  }
}
bool CampoDirCopier::Copy(const wxString& src, const wxString& dst, bool bOpenGL)
{ 
  wxBusyCursor hourglass;
  m_strSrc = src;
  m_strDst = dst;
  if (!wxDirExists(m_strDst)) // Utile precauzione
    wxMkdir(m_strDst); 
  wxDir dir(m_strSrc);
  dir.Traverse(*this);
  RenameDLL(wxT("OpenGL32.dll"), bOpenGL);
  RenameDLL(wxT("glu32.dll"), bOpenGL);
  return true;
}
#ifdef WIN32
#endif
///////////////////////////////////////////////////////////
// CampoWizardPage
///////////////////////////////////////////////////////////
class CampoWizardPage;  //predefinizione di CampoWizardPage (magia nera!!)
//predefinizione pure della CampoWizard con tutti i suoi metodi per poterlo usare nel metodo GetWizard (magia nerissima!!)
class CampoWizard : public wxWizard
{
  enum { m_nPages = 10 };  
  CampoWizardPage* m_pPage[m_nPages];
  wxString _strDestinationPath;       //path di aggiornamento/installazione
  unsigned int _uInstallationType;    //tipo di installazione selezionata (standard,server,client,aggiornamento)
  unsigned int _uDongleType;          //tipo di chiave di protezione (hardlock,eutron,server)
  wxString _strPrgLocPath;  //path programmi in locale
  wxString _strPrgNetPath;  //path programmi in remoto (server programmi directory per client)
  wxString _strDataPath;    //path dati (creare o usare)
  bool _bInstDemoData;      //installa dati dimostrativi
  bool _bInstUseAuth;       //installa/usa server authoriz
  wxString _strSrvAuth;     //nome server authoriz
  bool _bInstUseDict;       //installa/usa server diction
  wxString _strSrvDict;     //nome server diction
  
  unsigned int _iSrvAutostartMode;  //tipologia di esecuzione dei server
  bool _bDesktopShortcut;   //crea il link sul desktop
protected:
  DECLARE_EVENT_TABLE();
  int Pages() const { return m_nPages; }
  CampoWizardPage* Page(int p) const { return m_pPage[p]; }
  void OnNext(wxCommandEvent& e);
  
public:
  bool Run();
  wxString Get(wxWindowID id) const;
  int GetSelection(wxWindowID id) const;
  bool GetBool(wxWindowID id) const;
  
  //metodi per il passaggio tra le finestre dei parametri di installazione!
  void SetDestinationPath(const wxString& strPath);
  const wxString& GetDestinationPath() const;
  void SetInstallationType(const unsigned int uType);
  const unsigned int GetInstallationType() const;
  void SetDongleType(const unsigned int uType);
  const unsigned int GetDongleType() const;
  void SetPrgLocPath(const wxString& strPrgLocPath);
  const wxString& GetPrgLocPath() const;
  void SetPrgNetPath(const wxString& strPrgNetPath);
  const wxString& GetPrgNetPath() const;
  void SetDataPath(const wxString& strDataPath);
  const wxString& GetDataPath() const;
  void SetInstDemoData(const bool bInstDemoData);
  const bool GetInstDemoData() const;
  void SetInstUseAuth(const bool bInstUseAuth);
  const bool GetInstUseAuth() const;
  void SetSrvAuth(const wxString& strSrvAuth);
  const wxString& GetSrvAuth() const;
  void SetInstUseDict(const bool bInstUseDict);
  const bool GetInstUseDict() const;
  void SetSrvDict(const wxString& strSrvDict);
  const wxString& GetSrvDict() const;
  void SetSrvAutostartMode(const int iSrvAutostartMode);
  const int GetSrvAutostartMode() const;
  void SetDesktopShortcut(const bool bDesktopShortcut);
  const bool GetDesktopShortcut() const;
  CampoWizard(wxWindow* pParent);
};
////////////////////////////////////////////////////////////////////////////////////////////
//Classe per la gestione dei files di configurazione tipo campo.ini
class CampoIniFile : public wxFileConfig
{
protected:
public:
  wxString Get(const wxString strVariable) const;
  bool GetBool(const wxString strVariable) const;
  bool Set(const wxString strVariable, const wxString strValue);//, const wxString strParagraph) const;
  bool Set(const wxString strVariable, const int uValue);
  CampoIniFile(const wxString strIniPath, wxString strValue);
};
CampoIniFile::CampoIniFile(const wxString strIniPath, const wxString strParagraph)
            : wxFileConfig (wxEmptyString, wxEmptyString, wxEmptyString, strIniPath, 
              wxCONFIG_USE_GLOBAL_FILE|wxCONFIG_USE_NO_ESCAPE_CHARACTERS)
{
  if (!strParagraph.IsEmpty())
    SetPath(strParagraph);
}
wxString CampoIniFile::Get(const wxString strVariable) const
{
  return Read(strVariable);
}
bool CampoIniFile::GetBool(const wxString strVariable) const
{
  wxString strBool = Get(strVariable);
  return strBool == "X" || strBool == "Y";
}
bool CampoIniFile::Set(const wxString strVariable, const wxString strValue)//, const wxString strParagraph) const
{
  return Write(strVariable, strValue);
}
bool CampoIniFile::Set(const wxString strVariable, const int uValue)//, const wxString strParagraph) const
{
  return Write(strVariable, uValue);
}
////////////////////////////////////////////////////////////////////////////////////////////
//Campo wizard page (pagina generica del programma, di cui saranno figlie le singole pagine)
class CampoWizardPage : public wxWizardPageSimple
{
  wxHtmlWindow* m_pText;
protected:
  CampoWizard& GetWizard() const {return *(CampoWizard*)GetParent();}
  void SetHTMLText(const wxString strTitle, const wxString strBody);
  void SetHTMLPage(const wxString strFile);
  wxString Bold(const wxString strStr) const;
  void AddLabel(wxSizer* pSizer, const wxChar* label);
  void AddLabel(wxGridBagSizer* pSizer, const wxChar* label, unsigned int row, unsigned int column);
  bool CheckDataDir(wxString& strDataPath) const;
public:
  virtual bool ForwardValidate() { return true; }
  wxString Get(wxWindowID id) const;
  bool GetBool(wxWindowID id) const;
  bool Set(wxWindowID id, const wxString& str);
  bool Set(wxWindowID id, const bool bul);
  int GetSelection(wxWindowID id) const;
  
  CampoWizardPage(wxWizard* parent);
};
wxString CampoWizardPage::Get(wxWindowID id) const
{
  wxWindow* pWnd = FindWindowById(id);
  return pWnd ? pWnd->GetLabel() : wxEmptyString;
}
bool CampoWizardPage::GetBool(wxWindowID id) const
{
  wxCheckBox* pWnd = (wxCheckBox*)FindWindowById(id);
  return pWnd != NULL && pWnd->IsChecked();
}
bool CampoWizardPage::Set(wxWindowID id, const wxString& str)
{
  wxWindow* pWnd = FindWindowById(id);
  if (pWnd)
    pWnd->SetLabel(str);
  return (pWnd != NULL);
}
bool CampoWizardPage::Set(wxWindowID id, const bool bul)
{
  wxCheckBox* pWnd = (wxCheckBox*)FindWindowById(id);
  if (pWnd)
    pWnd->SetValue(bul);
  return (pWnd != NULL);
}
int CampoWizardPage::GetSelection(wxWindowID id) const
{
  int n = -1;
  wxWindow* pWnd = FindWindowById(id);
  if (pWnd)
  {
    wxChoice* pList = (wxChoice*)pWnd;
    n = pList->GetSelection();
  }
  return n;
}
void CampoWizardPage::SetHTMLPage(const wxString strFile)
{
   m_pText->LoadPage(strFile);
}
//parte html della finestra standard
void CampoWizardPage::SetHTMLText(wxString strTitle, wxString strBody)
{
  wxString strAppName = wxT(""); strAppName += Bold(APPNAME); strAppName += wxT("");
  strTitle.Replace(wxT("APPNAME"), strAppName);
  strBody.Replace(wxT("APPNAME"), strAppName);
  wxString str;
  str += wxT("");
  str += wxT(""); str += strTitle; str += wxT("
");
  str += wxT("
");
  str += wxT(""); str += strBody; str += wxT("
");
  str += wxT("");
  m_pText->SetPage(str);
}
wxString CampoWizardPage::Bold(const wxString strStr) const
{
  wxString strBold;
  strBold << "" << strStr << "";
  return strBold;
}
//metodo per aggiungere i prompt agli oggetti contenuti nelle GridSize e similia
void CampoWizardPage::AddLabel(wxSizer* pSizer, const wxChar* label)
{
  pSizer->Add(new wxStaticText(this, wxID_ANY, label), 0, wxALL|wxALIGN_CENTER_VERTICAL);
}
void CampoWizardPage::AddLabel(wxGridBagSizer* pSizer, const wxChar* label, unsigned int row, unsigned int column)
{
  pSizer->Add(new wxStaticText(this, wxID_ANY, label), wxGBPosition(row, column));
}
//metodo per il controllo della validita' di un'area dati
bool CampoWizardPage::CheckDataDir(wxString& strDataPath) const
{
  wxDir dirDataPath(strDataPath);
  bool ok_data = false;
  //deve esistere non vuota, e contenere la sottodirectory "com" con i dati comuni
  if (dirDataPath.Exists(strDataPath) && dirDataPath.HasSubDirs("com"))
  {
    strDataPath << "/com";
    wxFileName fnFileToCheck(strDataPath, "tabcom");
    fnFileToCheck.SetExt("dbf");
    if (fnFileToCheck.FileExists())
      ok_data = true;
  }
  return ok_data;
}
//costruttore della finestra standard
CampoWizardPage::CampoWizardPage(wxWizard* parent)
            : wxWizardPageSimple(parent)
{ 
  wxBoxSizer* pSizer = new wxBoxSizer(wxVERTICAL);
  m_pText = new wxHtmlWindow(this, 100, wxDefaultPosition, wxSize(512, 256));
  pSizer->Add(m_pText, 0, wxALL, 0);
  pSizer->AddSpacer(5);
  SetSizer(pSizer);
}
/**********************************************************************************************************/
/*    1   Pagina di benvenuto                                                                             */
/**********************************************************************************************************/
class CampoWizardPage1 : public CampoWizardPage
{
public:
  CampoWizardPage1(wxWizard* parent);
};
CampoWizardPage1::CampoWizardPage1(wxWizard* parent) : CampoWizardPage(parent)
{
  //contenuto della prima schermata (pagina benvenuto)
  wxString strTitle = wxT("Benvenuti in APPNAME");
  wxString strBody = wxT("Questo programma vi guiderà passo a passo nell'installazione / aggiornamento del software.
");
  strBody += wxT("Leggere attentamente le istruzioni che saranno visualizzate nelle finestre di questo programma di installazione!
");
  strBody += wxT("Prima di proseguire con l'installazione / aggiornamento assicurarsi di avere effettuato il login a Windows con un utente di tipo 'Amministratore' di sistema.
");
  strBody += wxT("In caso si desideri aggiornare una postazione tipo server di APPNAME su cui sia attivo il gestore dei servizi di APPNAME, arrestare prima tale gestore dei servizi.
");
  SetHTMLText(strTitle, strBody);
}
/**********************************************************************************************************/
/*    2   Pagina con la scelta di Aggiornamento / Tipo Installazione                                      */
/**********************************************************************************************************/
class CampoWizardPage2 : public CampoWizardPage
{
  wxRadioBox* m_pRadioBox;
protected:
  virtual bool ForwardValidate();
public:
  CampoWizardPage2(wxWizard* parent);
};
bool CampoWizardPage2::ForwardValidate()
{
  const int iLastRow = m_pRadioBox->GetRowCount() - 1;
  const int iSelectedRow = m_pRadioBox->GetSelection();
  wxString strPrgPath;
  wxString strStudy;
  wxString strSrvAuth;
  wxString strSrvDict;
  //analizza il campo.ini dell'installazione selezionata (si usa < perche' l'ultima row e' la nuova installazione!)
  if (iSelectedRow < iLastRow)
  {
    strPrgPath = m_pRadioBox->GetStringSelection();
    CampoIniFile CampoIni(strPrgPath + "/campo.ini", "Main");
    
    const bool bTestDatabase = CampoIni.GetBool("TestDatabase");
    //non si puo' aggiornare un client da cd!! va fatto dal programma
    const bool bTestPrograms = CampoIni.GetBool("TestPrograms");
    if (bTestPrograms)
    {
      CampoIniFile InstallIni(strPrgPath + "/install.ini", "Main");
      wxString strDiskPath = InstallIni.Get("DiskPath");
      wxString strMsg = "Per aggiornare questa stazione di lavoro e' necessario aggiornare prima il Server di ";
      strMsg << APPNAME << " in " << strDiskPath << " !\n";
      strMsg << "Questa stazione di lavoro si aggiornera' automaticamente alla prima esecuzione del programma " << APPNAME;
      return ErrorBox(strMsg);
    }
    strStudy = CampoIni.Get("Study");
    CampoIniFile CampoServerIni(strPrgPath + "/campo.ini", "Server");
    strSrvAuth = CampoServerIni.Get("Dongle");
    strSrvDict = CampoServerIni.Get("Dictionary");
    if (!CheckDataDir(strStudy))
      return ErrorBox("La cartella indicata come area dati NON e' valida!\nInterrompere l'installazione e selezionare un'area dati valida\ncon il programma Campo");
    GetWizard().SetDataPath(strStudy);
    if (!strSrvAuth.IsEmpty())
      GetWizard().SetSrvAuth(strSrvAuth);
    if (!strSrvDict.IsEmpty())
      GetWizard().SetSrvDict(strSrvDict);
    //setta alla pagina riassuntiva i valori della pagina attuale...
    GetWizard().SetDestinationPath(strPrgPath); //va alla pagina riassuntiva
    GetWizard().SetPrgLocPath(strPrgPath);  //questo serve solo per la creazione del link sul desktop!
    GetWizard().SetInstallationType(3);   //e' un aggiornamento!!
    GetWizard().SetDesktopShortcut(false);
  }
  else  //resetta il path in caso si scelga nuova installazione dopo aver scelto aggiornamento
  {
    GetWizard().SetDestinationPath("");
    GetWizard().SetDesktopShortcut(true);
  }
 
  return true;
}
CampoWizardPage2::CampoWizardPage2(wxWizard* parent) : CampoWizardPage(parent)
{
  //deve cercare campo.stp
  CampoIniFile campo_stp("C:\\campo.stp", "");
  wxString group;
  long index;
  const wxString program = "Program";
  wxArrayString asGroups, asCampi;
  //cerca se esiste campo.stp;se lo trova cerca quelle che sono le installazioni valide;se ne trova..
  //..le aggiunge ad un array di stringhe (asCampi) da cui genera un radiobutton di scelte
  for (bool ok = campo_stp.GetFirstGroup(group, index); ok; ok = campo_stp.GetNextGroup(group, index))
  {
    asGroups.Add(group);
  }
  int prechecked = -1;
  for (unsigned int i = 0; i < asGroups.GetCount(); i++)
  {
    CampoIniFile campo_stp("C:\\campo.stp", asGroups[i]);
    wxString path = campo_stp.Get(program);
  
    //sono installazioni valide quelle che presentano la coppia di files campo.ini e campo.aut (senza..
    //..questi 2 soggetti il programma non parte)
    wxString campo_ini = path;
    campo_ini << "/campo.ini";
    wxString campo_aut = path;
    campo_aut << "/campo.aut";
    if (wxFileName::FileExists(campo_ini) && wxFileName::FileExists(campo_aut))
    {
      asCampi.Add(path);
      //cerca l'eventuale installazione server se ci sono piu' installazioni sulla stessa macchina
      if (prechecked < 0)
      {
        CampoIniFile ini(campo_ini, "Main");
        if (ini.GetBool("TestDatabase") && !ini.GetBool("TestPrograms"))
          prechecked = i;
      }
    }
  }
  wxString strTitle, strBody;
  //se non ci sono delle installazioni da aggiornare propone solo installazioni..
	if (asCampi.IsEmpty())
	{
    strTitle += wxT("Scelta Installazione");
    strBody += wxT("E' possibile INSTALLARE Campo in un nuovo direttorio.
");
    asCampi.Add("Nuova installazione"); //voce di nuova installazione!
    m_pRadioBox = new wxRadioBox(this, 201, "Installazione del software", wxDefaultPosition, 
                               wxDefaultSize, asCampi, 0, wxRA_SPECIFY_ROWS);
  }
  //..senno' propone di aggiornare
  else
  {
    strTitle += wxT("Scelta Aggiornamento / Installazione");
    strBody += wxT("E' possibile AGGIORNARE (scelta consigliata) una installazione di Campo gia' presente oppure INSTALLARE in un nuovo direttorio.
");
    strBody += wxT("Selezionare l'opzione desiderata nel riquadro sottostante. In caso di piu' di una installazione ");
    strBody += wxT("presente sara' preselezionata la eventuale installazione di tipo Server, in quanto deve essere aggiornata per prima! ");
    strBody += wxT("
In questo caso procedere all'aggiornamento di tale installazione Server e aggiornare successivamente le postazioni client ");
    strBody += wxT("lanciando il programma Campo su di esse
");
    //radiobutton con le scelte aggiornamento
    asCampi.Add("Nuova installazione");
    m_pRadioBox = new wxRadioBox(this, 201, "Selezionare l'installazione da aggiornare (consigliato) o Nuova installazione", wxDefaultPosition, 
                               wxDefaultSize, asCampi, 0, wxRA_SPECIFY_ROWS);
    if (prechecked > 0)
      m_pRadioBox->SetSelection(prechecked);
  }
  strBody += wxT("Prima di proseguire accertarsi che non vi sia alcuna sessione di Campo attiva! ");
  strBody += wxT("Terminare quindi le eventuali sessioni di Campo attive e proseguire.
");
  SetHTMLText(strTitle, strBody);
  GetSizer()->Add(m_pRadioBox);
}
/**********************************************************************************************************/
//    3   Pagina con Accetta / Rifiuta la licenza
//*********************************************************************************************************/
class CampoWizardPage3 : public CampoWizardPage
{
protected:
  virtual bool ForwardValidate();
public:
  CampoWizardPage3(wxWizard* parent);
};
bool CampoWizardPage3::ForwardValidate()
{
  if (GetSelection(301) == 1)
    return ErrorBox("Impossibile proseguire se non si accetta la licenza sul software!!");
  return true;
}
CampoWizardPage3::CampoWizardPage3(wxWizard* parent) : CampoWizardPage(parent)
{
  SetHTMLPage("licenza.htm");
  //radiobutton Accetta / Rifiuta
  wxArrayString asAccRef;
  asAccRef.Add("Accetta");
  asAccRef.Add("Rifiuta");
  wxRadioBox* radio_box = new wxRadioBox(this, 301, "Selezionare 'Accetta' per proseguire con l'installazione, 'Rifiuta' per terminare l'installazione", wxDefaultPosition, 
                                         wxDefaultSize, asAccRef, 0, wxRA_SPECIFY_COLS);
  radio_box->SetSelection(1);
  GetSizer()->Add(radio_box);
}
/**********************************************************************************************************/
/*    4   Pagina con la gestione della chiave di protezione                                               */
/**********************************************************************************************************/
class CampoWizardPage4 : public CampoWizardPage
{
  int _dongle_type;
  wxButton* _butt_HL;
  wxButton* _butt_EU;
protected:
  DECLARE_EVENT_TABLE();
  void OnHLPick(wxCommandEvent& e);
  void OnEUPick(wxCommandEvent& e);
  int DongleTest();
  int ThisYear();
  wxString DecodeString(const wxString& data);
  int VersionYear();
  void BuildKey(char* key);
  bool HardlockGarble(unsigned short* data);
  unsigned short HardlockLogin(int& year);
  void EncodeEutronPassword(char* str);
  unsigned short EutronLogin(int& year);
public:
  CampoWizardPage4(wxWizard* parent);
};
//metodi per la gestione dei bottoni per l'esecuzione dei programmi di installazione delle chiavi
BEGIN_EVENT_TABLE(CampoWizardPage4, CampoWizardPage)
  EVT_BUTTON(401, OnHLPick)
  EVT_BUTTON(402, OnEUPick)
END_EVENT_TABLE()
void CampoWizardPage4::OnHLPick(wxCommandEvent& e)
{
  wxString path("../chiavi/hardlock/hldrv32.exe");
  wxExecute(path, wxEXEC_SYNC);
}
void CampoWizardPage4::OnEUPick(wxCommandEvent& e)
{
  wxString path("../chiavi/eutron/sdi.exe");
  wxExecute(path, wxEXEC_SYNC);
}
///////////////////////////////
// Gestione chiave Hardlock  //
///////////////////////////////
bool CampoWizardPage4::HardlockGarble(unsigned short* data)
{
  HL_CODE(data, 1);
  return true;
}
unsigned short CampoWizardPage4::HardlockLogin(int& year)
{
  unsigned short serno = 0xFFFF;
  unsigned char REFKEY[16] = "CAMPOKEY";
  unsigned char VERKEY[16] = "ìpÙˆ¬cê<";
  if (HL_LOGIN(26952, LOCAL_DEVICE, REFKEY, VERKEY) == STATUS_OK)
  { 
    unsigned short eprom[64]; memset(eprom, 0, sizeof(eprom));
    HL_READBL((unsigned char*)eprom);
    unsigned short data[4];
    memcpy(data, eprom, sizeof(data));
    HardlockGarble(data);
    if (data[0] == 0xFAE8)
      serno = data[1];
    else  
      serno = 0;
      
    memcpy(data, &eprom[60], sizeof(data));
    if (HardlockGarble(data))
      year = (int)data[0];
  }
  return serno;
}
///////////////////////////////
//   Gestione chiave Eutron  //
///////////////////////////////
void CampoWizardPage4::EncodeEutronPassword(char* str)
{
  const char* const key = "QSECOFR-";
  char tmp[16];
  int i;
  for (i = 0; str[i]; i++)
    tmp[i] = str[i] + (i < 8 ? key[i] : str[i - 8]);
  tmp[i] = '\0';
  strcpy(str, tmp);
}
unsigned short CampoWizardPage4::EutronLogin(int& year)
{
  unsigned short serno = 0xFFFF;
  
  const char* const login[2] = { "AGA.CAMPO", "25EBAI" };
  for (int i = 0; i < 2; i++)
  {
    KEY_NET eutron_key;
    memset(&eutron_key, 0, sizeof(KEY_NET));
    eutron_key.net_command = NET_KEY_OPEN;
    eutron_key.command = LOCATING_MODE;
  
    const char* const chiaro = login[i];
    char cifrato[16]; 
    strcpy(cifrato, chiaro);
    EncodeEutronPassword(cifrato);
  
    memset(eutron_key.label, 0, LABEL_LENGTH);
    strcpy((char*)eutron_key.label, chiaro);  
    memset(eutron_key.password, 0, PASSWORD_LENGTH);
    strcpy((char*)eutron_key.password, cifrato);  
    smartlink(&eutron_key);
    if (eutron_key.status == ST_OK)
    {
      eutron_key.net_command = NET_KEY_ACCESS;
      eutron_key.command = BLOCK_READING_MODE;
      short* pointer = (short*)(&eutron_key.data[0]);
      short* number  = (short*)(&eutron_key.data[2]);
      *pointer = 0; // Posizione in cui leggere
      *number = 8;  // Words da leggere
      smartlink(&eutron_key);
      if (eutron_key.status == ST_OK)
      {
        serno = (unsigned short)atol((const char*)eutron_key.data+4);
        if (i == 0)
        {
          const unsigned short y = *(unsigned short*)(eutron_key.data+12);
          if (y > 2000 && y < 3000)
            year = y;
        }
        else
          year = ThisYear();
        
        break;
      }
    }
  }  
  
  return serno;
}
/////////////////////////////////////////////////////////
// Metodi generici per le chiavi ed i relativi codici  //
/////////////////////////////////////////////////////////
void CampoWizardPage4::BuildKey(char* key)
{
  for (int i = 0; i < 8; i++)  
    key[i] = 'A'+ rand()%26;
}
int CampoWizardPage4::ThisYear()
{  
  int anno = 2006;
  time_t lt;
  if (time(<) == 0) 
  {
    struct tm* timeloc = localtime(<) ;
    if (timeloc != NULL)
      anno = timeloc->tm_year + 1900;
  }
  return anno;
}
wxString CampoWizardPage4::DecodeString(const wxString& data)
{                             
  char key[8] = "";
  BuildKey(key);
  char tmp[256];
  int i;
  for (i = 0; data[i]; i++)
    tmp[i] = data[i] - (i < 8 ? key[i] : tmp[i - 8]);
  tmp[i] = '\0';
  return tmp;
}
int CampoWizardPage4::VersionYear()
{                                                             
  char ver[32];
  GetPrivateProfileString("ba", "Versione", "", ver, sizeof(ver), "./program/install.ini");
  ver[4] = '\0';
  return atoi(ver);
}
int CampoWizardPage4::DongleTest()
{ 
	_dongle_type = 0;
  int yearKey = 0;
  
  unsigned int serno = HardlockLogin(yearKey);
  if (serno == 0xFFFF)
	{
    serno = EutronLogin(yearKey);   
		if (serno != 0xFFFF)
			_dongle_type = 2;		//chiave eutron
	}
	else
		_dongle_type = 1;	//chiave hardlock
    
  if (serno == 0)	// Chiave di sviluppo
    return _dongle_type;          
	if (serno == 0xFFFF)	// Chiave inesistente o invisibile = Prima installazione o demo
		return  _dongle_type;
  
  const int verYear = VersionYear();
  if (yearKey < verYear) // Chiave già programmata con assistenza pagata
	{  
		bool ok = false;
		wxFileInputStream file("./program/dninst.zip");
		if (file.IsOk())
		{
      wxTextInputStream keys(file);
			wxString line = keys.ReadLine();
			srand(883);
			DecodeString(line);
			const int ass_year = atoi(line);
			if (ass_year > yearKey) // Non devo abbassare l'anno di assistenza!
			{
				srand(ass_year);
				while (!file.Eof())
				{
					line = keys.ReadLine();
					line = DecodeString(line);
					unsigned int sn = (unsigned int)atol(line);
					if (sn == serno || line[0] == '*')
					{
						ok = true;
						break;
					}
				}
				if (ok)
				{
					const int n = ass_year%10;
					const int y = (ass_year / 1000) * 1000 + (ass_year%1000) /10;
					line.Printf("Il contratto di manutenzione %d/%d verrà attivato automaticamente", y, n);
					WarningBox(line);
				}
				else  
				{
					line.Printf("È necessario contattare l'assistenza tecnica\n"
												 "per l'abilitazione del contratto di manutenzione %d", verYear);
					WarningBox(line);
				}
			}
		} 
		else
		{
			ErrorBox("Impossibile verificare il contratto di manutenzione");
		}
	}
  return _dongle_type;
}
CampoWizardPage4::CampoWizardPage4(wxWizard* parent) : CampoWizardPage(parent)
{
  _dongle_type = DongleTest();	//controlla se la chiave c'e' ed eventualmente quale e'
  wxString strTitle = wxT("Controllo della chiave hardware di protezione");
  wxString strBody = wxT("La versione commerciale del software richiede l'installazione e la presenza della chiave hardware di protezione
");
  switch (_dongle_type)
  {
  case 1:
    strBody += wxT("E' stata rilevata una chiave tipo Hardlock:
");
    strBody += wxT("
");
    strBody += wxT("Si puo' procedere con l'installazione /aggiornamento del software Campo. Premere il pulsante \"Next\".
");
    break;
  case 2:
    strBody += wxT("E' stata rilevata una chiave tipo Eutron:
");
    strBody += wxT("
");
    strBody += wxT("Si puo' procedere con l'installazione /aggiornamento del software Campo. Premere il pulsante \"Next\".
");
    break;
  //case 3:   e' il caso del server di chiavi;la DongleTest() per ora non lo fa
    //break;
  default:
    strBody += wxT("Non e' stata rilevata alcuna chiave hardware installata !
");
    strBody += wxT("Per procedere all'installazione dei driver della chiave hardware collegata al computer premere il bottone corrispondente alla tipologia della chiave stessa.
");
    strBody += wxT("Se si desidera proseguire nell'installazione del software senza installare la chiave hardware cliccare su \"Next\".
");
    strBody += wxT("Quest'ultima procedura e' consigliata solo in caso di installazione tipo Client di rete senza chiave propria, ma che utilizza un server di autorizzazioni gia' installato e funzionante in rete.
");
    //procedura per la costruzione dei bottoni e delle immagini per l'installazione dei driver di chiave
    //"griglia" contenitrice degli oggetti
    wxBoxSizer* butt_box = new wxBoxSizer(wxHORIZONTAL);
    GetSizer()->Add(butt_box, 0, wxALIGN_CENTER_HORIZONTAL, 0);
    //Hardlock img e button
    wxBitmap bmp_HL("hardlock.gif", wxBITMAP_TYPE_GIF);
    wxStaticBitmap* s_bmp_HL = new wxStaticBitmap(this, wxID_ANY, bmp_HL);
    butt_box->Add(s_bmp_HL, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 8);
    _butt_HL = new wxButton(this, 401, "Hardlock", wxDefaultPosition, wxSize(100, 50));
    butt_box->Add(_butt_HL, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 8);
    //spaziatore centrale
    butt_box->AddSpacer(24);
    //Eutron img e button
    _butt_EU = new wxButton(this, 402, "Eutron", wxDefaultPosition, wxSize(100, 50));
    butt_box->Add(_butt_EU, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 8);
    wxBitmap bmp_EU("eutron.gif", wxBITMAP_TYPE_GIF);
    wxStaticBitmap* s_bmp_EU = new wxStaticBitmap(this, wxID_ANY, bmp_EU);
    butt_box->Add(s_bmp_EU, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 8);
    break;
  }
  
  SetHTMLText(strTitle, strBody);
  //aggiorna il tipo di chiave per poterlo scrivere sul campo.ini
  GetWizard().SetDongleType(_dongle_type);
}
/**********************************************************************************************************/
//    5 Scelta tipo installazione
/**********************************************************************************************************/
class CampoWizardPage5 : public CampoWizardPage
{
  wxRadioBox* m_pRadioBox;
protected:
  virtual bool ForwardValidate();
public:
  CampoWizardPage5(wxWizard* parent);
};
bool CampoWizardPage5::ForwardValidate()
{
  const unsigned int type = m_pRadioBox->GetSelection();
  GetWizard().SetInstallationType(type);
  return true;
}
CampoWizardPage5::CampoWizardPage5(wxWizard* parent) : CampoWizardPage(parent)
{
  //Istruzioni per l'uso!
  wxString strTitle = wxT("Scelta del tipo di installazione");
  wxString strBody = wxT("Standard (scelta consigliata). Installazione su postazione singola, con programmi e dati sul disco locale del computer
");
  strBody += wxT("Installazioni di rete (per utenti esperti)
");
  strBody += wxT("Server: Computer in rete sul quale sono presenti una copia, utilizzata o meno, dei programmi (server programmi) e l’area dati (server dati). ");
  strBody += wxT("In una installazione in rete di Campo e' necessario sia presente un unica postazione di tipo server, ");
  strBody += wxT("e deve essere installata per prima!
");
  strBody += wxT("Client: Computer in rete sul quale e' presente una copia dei programmi ma non l'area dati. ");
  strBody += wxT("I client possono essere installati solo dopo l'installazione del server!
");
  SetHTMLText(strTitle, strBody);
  //radiobutton con i tipi di installazione
  wxArrayString asInstType;
  asInstType.Add("Standard");
  asInstType.Add("Server");
  asInstType.Add("Client");
  m_pRadioBox = new wxRadioBox(this, 501, "Selezionare il tipo di installazione", wxDefaultPosition, 
                             wxDefaultSize, asInstType, 0, wxRA_SPECIFY_ROWS);
  //setta il default a Standard
  m_pRadioBox->SetSelection(0);
  GetSizer()->Add(m_pRadioBox);
}
/**********************************************************************************************************/
//    6   Installazione standard
/**********************************************************************************************************/
class CampoWizardPage6 : public CampoWizardPage
{
protected:
  DECLARE_EVENT_TABLE();
  void OnDirPick(wxCommandEvent& e);
  virtual bool ForwardValidate();
public:
  CampoWizardPage6(wxWizard* parent);
};
BEGIN_EVENT_TABLE(CampoWizardPage6, CampoWizardPage)
  EVT_BUTTON(602, OnDirPick)
  EVT_BUTTON(604, OnDirPick)
END_EVENT_TABLE()
void CampoWizardPage6::OnDirPick(wxCommandEvent& e)
{
  const wxWindowID wiTargetField = e.GetId() - 1;
  wxString strPath = Get(wiTargetField);
  wxDirDialog dlg(this, wxDirSelectorPromptStr, strPath, 
                  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
  if (dlg.ShowModal() == wxID_OK)
  {
    strPath = dlg.GetPath();
    Set(wiTargetField, strPath);
  }
}
//metodo per il controllo dell'area dati;se la directory indicata non e' vuota non puoi usarla ne' crearla
bool CampoWizardPage6::ForwardValidate()
{
  //controllo esistenza directory vuota per i programmi in locale
  const wxString strPrgLocPath = Get(601);
  wxDir dirPrgLocPath(strPrgLocPath);
  if (dirPrgLocPath.Exists(Get(601)) && (dirPrgLocPath.HasFiles() || dirPrgLocPath.HasSubDirs()))
    return ErrorBox("La cartella selezionata per l'installazione dei programmi NON e' valida! Selezionarne un'altra!");
  const wxString strDataPath = Get(603);
  wxDir dirDataPath(strDataPath);
  if (dirDataPath.Exists(strDataPath) && (dirDataPath.HasFiles() || dirDataPath.HasSubDirs()))
    return ErrorBox("La cartella indicata per la creazione dell'area dati non e' vuota! Selezionarne un'altra!");
  //setta alla pagina riassuntiva i valori della pagina attuale...
  GetWizard().SetPrgLocPath(strPrgLocPath);
  GetWizard().SetDataPath(strDataPath);
  //...e pure quegli stupidi datidemo che nessuno ha mai installato!!
  const bool bInstDemoData = GetBool(605);
  GetWizard().SetInstDemoData(bInstDemoData);
  return true;
}
CampoWizardPage6::CampoWizardPage6(wxWizard* parent) : CampoWizardPage(parent)
{
  wxString strTitle = wxT("Installazione di tipo Standard");
  wxString strBody = wxT("Digitare nel campo 'Cartella programma' il percorso completo della cartella dove si desidera installare il programma. ");
  strBody += wxT("Il percorso di default (consigliato) e' C:\\Campo 
");
  strBody += wxT("Digitare nel campo 'Cartella Dati' il percorso completo della cartella dove si desidera installare l'area dati. ");
  strBody += wxT("Il percorso di default (consigliato) e' C:\\Campo\\dati 
");
  strBody += wxT("Dati dimostrativi: area dati precompilata per esemplificare il funzionamento del software. ");
  strBody += wxT("Di norma NON vanno caricati nel caso di una normale installazione!
");
  SetHTMLText(strTitle, strBody);
  //griglia per sistemare i campi
  wxGridBagSizer* gbsSizer = new wxGridBagSizer(VGAP, HGAP);
  GetSizer()->Add(gbsSizer);
  
  //prima riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella programmi", 0, 0);
  //campo testo
  wxString strPath;
  strPath = "C:\\";
  strPath += APPNAME;
  wxTextCtrl* tcPrgPath = new wxTextCtrl(this, 601, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcPrgPath, wxGBPosition(0, 1));
  //bottone 'sfoglia'
  wxButton* bPrgButton = new wxButton(this, 602, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bPrgButton, wxGBPosition(0, 2));
  //seconda riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella dati", 1, 0);
  //campo testo
  strPath += "/dati";
  wxTextCtrl* tcDataPath = new wxTextCtrl(this, 603, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcDataPath, wxGBPosition(1, 1));
  //bottone 'sfoglia'
  wxButton* bDataButton = new wxButton(this, 604, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bDataButton, wxGBPosition(1, 2));
  //terza riga della griglia
  wxCheckBox* chDataDemo = new wxCheckBox(this, 605, wxT("Carica i dati dimostrativi"));
  chDataDemo->SetValue(false);
  gbsSizer->Add(chDataDemo, wxGBPosition(2, 1));
}
/**********************************************************************************************************/
//    7   Installazione server
/**********************************************************************************************************/
class CampoWizardPage7 : public CampoWizardPage
{
  wxRadioBox* m_pRadioBox;
protected:
  DECLARE_EVENT_TABLE();
  virtual bool ForwardValidate();
  void OnDirPick(wxCommandEvent& e);
  void OnSrvClick(wxCommandEvent& e);
public:
  CampoWizardPage7(wxWizard* parent);
};
BEGIN_EVENT_TABLE(CampoWizardPage7, CampoWizardPage)
  EVT_BUTTON(702, OnDirPick)
  EVT_BUTTON(704, OnDirPick)
  EVT_CHECKBOX(705, OnSrvClick)
  EVT_CHECKBOX(707, OnSrvClick)
END_EVENT_TABLE()
void CampoWizardPage7::OnDirPick(wxCommandEvent& e)
{
  const wxWindowID wiTargetField = e.GetId() - 1;
  wxString strPath = Get(wiTargetField);
  wxDirDialog dlg(this, wxDirSelectorPromptStr, strPath, 
                  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
  if (dlg.ShowModal() == wxID_OK)
  {
    strPath = dlg.GetPath();
    Set(wiTargetField, strPath);
  }
}
void CampoWizardPage7::OnSrvClick(wxCommandEvent& e)
{
  //nome del server
  wxWindow* pWnd = FindWindowById(e.GetId() + 1);
  if (pWnd)
    pWnd->Enable(e.IsChecked());
  //tipo installazione server
  pWnd = FindWindowById(709);
  if (pWnd)
    pWnd->Enable(GetBool(705) || GetBool(707));
}
bool CampoWizardPage7::ForwardValidate()
{
  //controllo esistenza directory vuota per i programmi in locale
  const wxString strPrgLocPath = Get(701);
  wxDir dirPrgLocPath(strPrgLocPath);
  if (dirPrgLocPath.Exists(strPrgLocPath) && (dirPrgLocPath.HasFiles() || dirPrgLocPath.HasSubDirs()))
    return ErrorBox("La cartella selezionata per l'installazione dei programmi NON e' valida! Selezionarne un'altra!");
  //controllo della directory dell'area dati: deve essere nuova o vuota affinche' possa essere utilizzata!!
  const wxString strDataPath = Get(703);
  wxDir dirDataPath(strDataPath);
  if (dirDataPath.Exists(strDataPath) && (dirDataPath.HasFiles() || dirDataPath.HasSubDirs()))
    return ErrorBox("La cartella indicata per la creazione dell'area dati non e' vuota! Selezionarne un'altra!");
  //setta alla pagina riassuntiva i valori della pagina attuale...
  GetWizard().SetPrgLocPath(strPrgLocPath);
  GetWizard().SetDataPath(strDataPath);
  //...compresi eventuali stupidi servers!
  const bool bInstAuth = GetBool(705);
  if (bInstAuth)
  {
    GetWizard().SetInstUseAuth(bInstAuth);
    const wxString strSrvAuth = Get(706);
    if (strSrvAuth.IsEmpty())
      return ErrorBox("Specificare il server gestore delle autorizzazioni!");
    GetWizard().SetSrvAuth(strSrvAuth);
  }
  else
    GetWizard().SetSrvAuth("");
  const bool bInstDict = GetBool(707);
  if (bInstDict)
  {
    GetWizard().SetInstUseDict(bInstDict);
    const wxString strSrvDict = Get(708);
    if (strSrvDict.IsEmpty())
      return ErrorBox("Specificare il server gestore dei dizionari!");
    GetWizard().SetSrvDict(strSrvDict);
  }
  else
    GetWizard().SetSrvDict("");
  //..e loro modalita' di esecuzione
  if (bInstAuth || bInstDict)
  {
    GetWizard().SetSrvAutostartMode(m_pRadioBox->GetSelection());
  }
  else
    GetWizard().SetSrvAutostartMode(-1);
  return true;
}
CampoWizardPage7::CampoWizardPage7(wxWizard* parent) : CampoWizardPage(parent)
{
  wxString strTitle = wxT("Installazione di tipo Server");
  wxString strBody = wxT("Digitare nel campo 'Cartella programma' il percorso completo della cartella dove si desidera installare il programma. ");
  strBody += wxT("Il percorso consigliato e' C:\\Campo 
");
  strBody += wxT("Digitare nel campo 'Cartella dati' il percorso completo della cartella dove si desidera installare l'area dati. ");
  strBody += wxT("Il percorso consigliato e' C:\\Campo\\dati 
");
  strBody += wxT("Le cartelle del programma e dei dati dovranno essere condivise in modalita' lettura/scrittura agli utenti di sistema e di rete che utilizzeranno il software Campo. ");
  strBody += wxT("In mancanza di tale condivisione nessun client potra' accedere al server!
");
  strBody += wxT("Gestore autorizzazioni: e' il software che permette di gestire una chiave di protezione hardware multiutenza condivisa in rete. ");
  strBody += wxT("Installando tale software e' necessario specificare il computer su cui e' montata la chiave di protezione multiutenza.");
  strBody += wxT("Viene di default proposto il computer su cui si sta eseguendo l'installazione di APPNAME (localhost).
");
  strBody += wxT("Gestore dizionari: e' il software che permette di utilizzare APPNAME in lingue diverse dall'italiano. ");
  strBody += wxT("Per l'installazione di questo software viene di default proposto il computer su cui si sta eseguendo l'installazione di APPNAME (localhost).
");
  strBody += wxT("Modalita' di esecuzione programmi di gestione
");
  strBody += wxT("Come servizi: i programmi di gestione vengono eseguiti come servizi di Windows; questa e' la modalita' consigliata ed e' obbligatoria in caso di installazione con Windows 2003
");
  strBody += wxT("Nel menu esecuzione automatica: i programmi di gestione vengono eseguiti automaticamente al primo accesso di un utente al server di APPNAME; usare questa modalita' solo nell'impossibilita' di utilizzare la precedente
");
  SetHTMLText(strTitle, strBody);
  //griglia per sistemare i campi
  wxGridBagSizer* gbsSizer = new wxGridBagSizer(VGAP, HGAP);
  GetSizer()->Add(gbsSizer);
  //prima riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella programmi", 0, 0);
  //campo testo
  wxString strPath;
  strPath = "C:\\";
  strPath += APPNAME;
  wxTextCtrl* tcPrgPath = new wxTextCtrl(this, 701, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcPrgPath, wxGBPosition(0, 1));
  //bottone 'sfoglia'
  wxButton* bPrgButton = new wxButton(this, 702, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bPrgButton, wxGBPosition(0, 2));
  //seconda riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella dati", 1, 0);
  //campo testo
  strPath += "/dati";
  wxTextCtrl* tcDataPath = new wxTextCtrl(this, 703, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcDataPath, wxGBPosition(1, 1));
  //bottone 'sfoglia'
  wxButton* bDataButton = new wxButton(this, 704, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bDataButton, wxGBPosition(1, 2));
  //terza riga della griglia
  //check installa authoriz
  wxCheckBox* chAuthoriz = new wxCheckBox(this, 705, wxT("Installa il gestore delle autorizzazioni"));
  chAuthoriz->SetValue(false);
  gbsSizer->Add(chAuthoriz, wxGBPosition(2, 1));
  //server authoriz
  wxTextCtrl* tcAuthoriz = new wxTextCtrl(this, 706, "localhost", wxDefaultPosition, wxSize(96,-1));
  tcAuthoriz->Disable();
  gbsSizer->Add(tcAuthoriz, wxGBPosition(2, 2));
  //quarta riga della griglia
  //check installa diction
  wxCheckBox* chDictionary = new wxCheckBox(this, 707, wxT("Installa il gestore dei dizionari"));
  chDictionary->SetValue(false);
  gbsSizer->Add(chDictionary, wxGBPosition(3, 1));
  //server diction
  wxTextCtrl* tcDiction = new wxTextCtrl(this, 708, "localhost", wxDefaultPosition, wxSize(96,-1));
  tcDiction->Disable();
  gbsSizer->Add(tcDiction, wxGBPosition(3, 2));
  //quinta riga della griglia
  //radiobutton con i tipi di installazione
  wxArrayString asInstType;
  asInstType.Add("Come servizi (consigliato)");
  asInstType.Add("Nel menu esecuzione automatica");
  m_pRadioBox = new wxRadioBox(this, 709, "Modalita' di esecuzione gestori", wxDefaultPosition, 
                             wxDefaultSize, asInstType, 0, wxRA_SPECIFY_COLS);
  //setta il default a "come servizio"
  m_pRadioBox->SetSelection(0);
  m_pRadioBox->Disable();
  gbsSizer->Add(m_pRadioBox, wxGBPosition(4, 1));
}
/**********************************************************************************************************/
//    8   Installazione client
/**********************************************************************************************************/
class CampoWizardPage8 : public CampoWizardPage
{
protected:
  DECLARE_EVENT_TABLE();
  virtual bool ForwardValidate();
  void OnDirPick(wxCommandEvent& e);
  void OnSrvClick(wxCommandEvent& e);
public:
  CampoWizardPage8(wxWizard* parent);
};
BEGIN_EVENT_TABLE(CampoWizardPage8, CampoWizardPage)
  EVT_BUTTON(802, OnDirPick)
  EVT_BUTTON(804, OnDirPick)
  EVT_BUTTON(806, OnDirPick)
  EVT_CHECKBOX(807, OnSrvClick)
  EVT_CHECKBOX(809, OnSrvClick)
END_EVENT_TABLE()
void CampoWizardPage8::OnDirPick(wxCommandEvent& e)
{
  const wxWindowID wiTargetField = e.GetId() - 1;
  wxString strPath = Get(wiTargetField);
  wxDirDialog dlg(this, wxDirSelectorPromptStr, strPath, 
                  wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
  if (dlg.ShowModal() == wxID_OK)
  {
    strPath = dlg.GetPath();
    Set(wiTargetField, strPath);
  }
}
void CampoWizardPage8::OnSrvClick(wxCommandEvent& e)
{
  wxWindow* pWnd = FindWindowById(e.GetId() + 1);
  if (pWnd)
    pWnd->Enable(e.IsChecked());
}
bool CampoWizardPage8::ForwardValidate()
{
  //controllo esistenza directory vuota per i programmi in locale
  const wxString strPrgLocPath = Get(801);
  wxDir dirPrgLocPath(strPrgLocPath);
  if (dirPrgLocPath.Exists(strPrgLocPath) && (dirPrgLocPath.HasFiles() || dirPrgLocPath.HasSubDirs()))
    return ErrorBox("La cartella selezionata per l'installazione dei programmi NON e' valida! Selezionarne un'altra!");
  //controllo esistenza directory e programmi sul server
  const wxString strPrgNetPath = Get(803);
  wxDir dirPrgPath(strPrgNetPath);
  bool ok_prg = false;
  //deve esistere non vuota, e contenere almeno campo.ini,install.ini,campo.aut,ba0.exe
  if (dirPrgPath.Exists(strPrgNetPath) && dirPrgPath.HasFiles() && dirPrgPath.HasSubDirs())
  {
    wxFileName fnFileToCheck(strPrgNetPath, "campo");
    fnFileToCheck.SetExt("ini");
    if (fnFileToCheck.FileExists())
    {
      fnFileToCheck.SetName("install");
      fnFileToCheck.SetExt("ini");
      if (fnFileToCheck.FileExists())
      {
        fnFileToCheck.SetName("campo");
        fnFileToCheck.SetExt("aut");
        if (fnFileToCheck.FileExists())
        {
          fnFileToCheck.SetName("ba0");
          fnFileToCheck.SetExt("exe");
          if (fnFileToCheck.FileExists())
          {
            ok_prg = true;
          }
        }
      }
    }
  }
  if (!ok_prg)
    return ErrorBox("La cartella selezionata come origine dei programmi NON e' valida!");
  //controllo esistenza dati sul server
  wxString strDataPath = Get(805);
  if (!CheckDataDir(strDataPath))
    return ErrorBox("La cartella selezionata come area dati NON e' valida!");
  //setta alla pagina riassuntiva i valori della pagina attuale
  GetWizard().SetPrgLocPath(strPrgLocPath);
  GetWizard().SetPrgNetPath(strPrgNetPath);
  GetWizard().SetDataPath(strDataPath);
    //...compresi eventuali stupidi servers!
  const bool bUseAuth = GetBool(807);
  if (bUseAuth)
  {
    GetWizard().SetInstUseAuth(bUseAuth);
    const wxString strSrvAuth = Get(808);
    if (strSrvAuth.IsEmpty())
      return ErrorBox("Specificare il computer gestore delle autorizzazioni!");
    GetWizard().SetSrvAuth(strSrvAuth);
  }
  else
    GetWizard().SetSrvAuth("");
  const bool bUseDict = GetBool(809);
  if (bUseDict)
  {
    GetWizard().SetInstUseDict(bUseDict);
    const wxString strSrvDict = Get(810);
    if (strSrvDict.IsEmpty())
      return ErrorBox("Specificare il computer gestore dei dizionari!");
    GetWizard().SetSrvDict(strSrvDict);
  }
  else
    GetWizard().SetSrvDict("");
  return true;
}
CampoWizardPage8::CampoWizardPage8(wxWizard* parent) : CampoWizardPage(parent)
{
  wxString strTitle = wxT("Installazione di tipo Client");
  wxString strBody = wxT("Digitare nel campo 'Cartella locale programma' il percorso completo della cartella dove si desidera installare il programma. ");
  strBody += wxT("Il percorso consigliato e' C:\\Campo 
");
  strBody += wxT("Digitare nel campo 'Cartella remota origine programmi' il percorso completo della cartella di rete dove sono i files origine del programma. ");
  strBody += wxT("E' la cartella di programmi condivisa dal server precedentemente installato.
");
  strBody += wxT("Digitare nel campo 'Cartella remota dati da utilizzare' il percorso completo della cartella di rete dove sono i dati. ");
  strBody += wxT("E' la cartella dei dati condivisa dal server precedentemente installato.
");
  strBody += wxT("Gestore autorizzazioni: e' il computer gestore di una chiave di protezione hardware multiutenza condivisa in rete. ");
  strBody += wxT("Generalmente e' il computer che agente da server di APPNAME e su cui deve essere montata la chiave di protezione multiutenza.
");
  strBody += wxT("Gestore dizionari: e' il computer gestore dei dizionari di APPNAME in lingue diverse dall'italiano. ");
  strBody += wxT("Generalmente e' il computer che agente da server di APPNAME.
");
 
  SetHTMLText(strTitle, strBody);
  //griglia per sistemare i campi
  wxGridBagSizer* gbsSizer = new wxGridBagSizer(VGAP, HGAP);
  GetSizer()->Add(gbsSizer);
  //prima riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella locale programma", 0, 0);
  //campo testo
  wxString strPath;
  strPath = "C:\\";
  strPath += APPNAME;
  wxTextCtrl* tcDestPrgPath = new wxTextCtrl(this, 801, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcDestPrgPath, wxGBPosition(0, 1));
  //bottone 'sfoglia'
  wxButton* bDestPrgButton = new wxButton(this, 802, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bDestPrgButton, wxGBPosition(0, 2));
  //seconda riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella remota origine programmi", 1, 0);
  //campo testo
  strPath = "Z:\\";
  strPath += APPNAME;
  wxTextCtrl* tcSrcPrgPath = new wxTextCtrl(this, 803, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcSrcPrgPath, wxGBPosition(1, 1));
  //bottone 'sfoglia'
  wxButton* bSrcPrgButton = new wxButton(this, 804, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bSrcPrgButton, wxGBPosition(1, 2));
  //terza riga della griglia
  //prompt
  AddLabel(gbsSizer, "Cartella remota dati da utilizzare", 2, 0);
  //campo testo
  strPath += "/dati";
  wxTextCtrl* tcDataPath = new wxTextCtrl(this, 805, strPath, wxDefaultPosition, wxSize(320,-1));
  gbsSizer->Add(tcDataPath, wxGBPosition(2, 1));
  //bottone 'sfoglia'
  wxButton* bDataButton = new wxButton(this, 806, wxT("Sfoglia"), wxDefaultPosition, wxSize(48, -1));
  gbsSizer->Add(bDataButton, wxGBPosition(2, 2));
  //quarta riga della griglia
  //check usa authoriz
  wxCheckBox* chAuthoriz = new wxCheckBox(this, 807, wxT("Utilizza il gestore delle autorizzazioni"));
  chAuthoriz->SetValue(false);
  gbsSizer->Add(chAuthoriz, wxGBPosition(3, 1));
  //quale e' il server authoriz
  wxTextCtrl* tcAuthoriz = new wxTextCtrl(this, 808, "nomeserverautorizzazioni", wxDefaultPosition, wxSize(96,-1));
  tcAuthoriz->Disable();
  gbsSizer->Add(tcAuthoriz, wxGBPosition(3, 2));
  //quarta riga della griglia
  //check usa diction
  wxCheckBox* chDictionary = new wxCheckBox(this, 809, wxT("Utilizza il gestore dei dizionari"));
  chDictionary->SetValue(false);
  gbsSizer->Add(chDictionary, wxGBPosition(4, 1));
  //quale e' il server diction
  wxTextCtrl* tcDiction = new wxTextCtrl(this, 810, "nomeserverdizionario", wxDefaultPosition, wxSize(96,-1));
  tcDiction->Disable();
  gbsSizer->Add(tcDiction, wxGBPosition(4, 2));
}
/**********************************************************************************************************/
//    9   pagina con la creazione icona sul desktop e lanciatore del lurch
/**********************************************************************************************************/
class CampoWizardPage9 : public CampoWizardPage
{
protected:
  virtual bool TransferDataToWindow();
  virtual bool ForwardValidate();
public:
  CampoWizardPage9(wxWizard* parent);
};
bool CampoWizardPage9::TransferDataToWindow()
{
  return Set(901, GetWizard().GetDesktopShortcut());
}
bool CampoWizardPage9::ForwardValidate()
{
  const bool bDesktopShortcut = GetBool(901);
  GetWizard().SetDesktopShortcut(bDesktopShortcut);
  return true;
}
CampoWizardPage9::CampoWizardPage9(wxWizard* parent) : CampoWizardPage(parent)
{
  wxString strTitle = wxT("Collegamenti");
  wxString strBody;
  strBody += wxT("E' possibile creare l'icona di APPNAME sul desktop 
");
  SetHTMLText(strTitle, strBody);
  wxCheckBox* pIcon = new wxCheckBox(this, 901, wxT("Creare l'icona sul desktop"));
  GetSizer()->Add(pIcon, 0, wxALL, 0);
  GetSizer()->AddSpacer(5);
  //wxCheckBox* pLink = new wxCheckBox(this, 1002, wxT("Associare i file .caz al programma"));
  //pLink->SetValue(true);
  //GetSizer()->Add(pLink, 0, wxALL, 0);
}
/**********************************************************************************************************/
//    10   pagina con la selezione di destinazione
/**********************************************************************************************************/
class CampoWizardPage10 : public CampoWizardPage
{
  unsigned int _uInstallType;
  wxString _strInstallType;
  wxString _strPrgLocPath;
  wxString _strPrgNetPath;
  wxString _strDataPath;
  wxString _strSrvAuth;
  wxString _strSrvDict;
  unsigned int _iSrvAutostartMode;
  bool _bInstDemoData;
  bool _bDesktopShortcut;
protected:
  virtual bool TransferDataToWindow();
public:
  CampoWizardPage10(wxWizard* parent);
};
bool CampoWizardPage10::TransferDataToWindow()
{
  CampoWizard& cw = GetWizard();
  _uInstallType = cw.GetInstallationType();
  switch (_uInstallType)
  {
  case 1: //server
    _strInstallType = "Server";
    _strPrgLocPath = cw.GetPrgLocPath();
    _strDataPath = cw.GetDataPath();
    _strSrvAuth = cw.GetSrvAuth();
    _strSrvDict = cw.GetSrvDict();
    _iSrvAutostartMode = cw.GetSrvAutostartMode();
    break;
  case 2: //client
    _strInstallType = "Client";
    _strPrgLocPath = cw.GetPrgLocPath();
    _strPrgNetPath = cw.GetPrgNetPath();
    _strDataPath = cw.GetDataPath();
    _strSrvAuth = cw.GetSrvAuth();
    _strSrvDict = cw.GetSrvDict();
    break;
  case 3: //aggiornamento
    _strInstallType = "";
    _strPrgLocPath = cw.GetDestinationPath();
    _strDataPath = cw.GetDataPath();
    _strSrvAuth = cw.GetSrvAuth();
    _strSrvDict = cw.GetSrvDict();
    break;
  default:  //standard
    _strInstallType = "Standard";
    _strPrgLocPath = cw.GetPrgLocPath();
    _strDataPath = cw.GetDataPath();
    _bInstDemoData = cw.GetInstDemoData();
    break;
  }
  //questo vale per tutti
  _bDesktopShortcut = cw.GetDesktopShortcut();
  //se installazione o aggiornamento cambia sia il titolo che i contenuti
  wxString strTitle;
  wxString strBody;
  //Aggiornamento
  if (_uInstallType == 3)
  {
    strTitle += wxT("AGGIORNAMENTO: riepilogo configurazione");
    
    strBody = wxT("Cartella programma da aggiornare:  ");
    strBody += wxT(Bold(_strPrgLocPath) + "
");
    strBody += wxT("Cartella dati in uso:  ");
    strBody += wxT(Bold(_strDataPath) + "
");
  }
  else  //Installazione
  {
    strTitle += wxT("INSTALLAZIONE: riepilogo configurazione");
    strBody = wxT("Tipo installazione selezionata:  ");
    strBody += wxT(Bold(_strInstallType) + "
");
    strBody += wxT("Cartella dove installare il programma:  ");
    strBody += wxT(Bold(_strPrgLocPath) + "
");
    if (_uInstallType == 2)
    {
      strBody += wxT("Cartella di origine dei files del programma:  ");
      strBody += wxT(Bold(_strPrgNetPath) + "
");
    }
    strBody += wxT("Cartella dati da creare:  ");
    strBody += wxT(Bold(_strDataPath) + "
");
  }
  //installazione servers...
  if (!_strSrvAuth.IsEmpty())
  {
    strBody += wxT("Computer gestore delle autorizzazioni:  ");
    strBody += wxT(Bold(_strSrvAuth) + "
");
  }
  if (!_strSrvDict.IsEmpty())
  {
    strBody += wxT("Computer gestore dei dizionari:  ");
    strBody += wxT(Bold(_strSrvDict) + "
");
  }
  //...e loro modalita' di lancio (solo installazione server!)
  if (_uInstallType == 1 && _iSrvAutostartMode >= 0)
  {
    strBody += wxT("Modalita' di esecuzione dei programmi di gestione:  ");
    if (_iSrvAutostartMode == 0)
      strBody += wxT(Bold("Come servizi") + "
");
    else
      strBody += wxT(Bold("Nel menu esecuzione automatica") + "
");
  }
  //installazione dati demo (solo in postazione singola)
  if (_uInstallType == 0 && _bInstDemoData)
    strBody += wxT("Installazione area dati dimostrativa
");
  if (_bDesktopShortcut)
    strBody += wxT("Creazione dell' icona sul desktop
");
  SetHTMLText(strTitle, strBody);
  return true;
}
CampoWizardPage10::CampoWizardPage10(wxWizard* parent) : CampoWizardPage(parent)
{
}
///////////////////////////////////////////////////////////
// CampoWizard
///////////////////////////////////////////////////////////
//la dichiarazione della classe e' prima in quanto alcuni suoi metodi sono usati da altre classi scritte piu' su
BEGIN_EVENT_TABLE(CampoWizard, wxWizard)
  EVT_BUTTON(wxID_FORWARD, CampoWizard::OnNext)
END_EVENT_TABLE()
void CampoWizard::OnNext(wxCommandEvent& e)
{
  CampoWizardPage* p = (CampoWizardPage*)GetCurrentPage();
  if (p->ForwardValidate())
    e.Skip();
}
bool CampoWizard::Run() 
{ return RunWizard(Page(0)); }
wxString CampoWizard::Get(wxWindowID id) const
{
  wxWindow* pWnd = FindWindowById(id);
  return pWnd ? pWnd->GetLabel() : wxEmptyString;
}
int CampoWizard::GetSelection(wxWindowID id) const
{
  int n = -1;
  wxWindow* pWnd = FindWindowById(id);
  if (pWnd)
  {
    wxChoice* pList = (wxChoice*)pWnd;
    n = pList->GetSelection();
  }
  return n;
}
bool CampoWizard::GetBool(wxWindowID id) const
{
  wxCheckBox* pWnd = (wxCheckBox*)FindWindowById(id);
  return pWnd != NULL && pWnd->IsChecked();
}
//lunga litania di metodi per gettare e settare i valori tra le pagine
void CampoWizard::SetDestinationPath(const wxString& path)
{
  _strDestinationPath = path;
  //Se il path di destinazione e' vuoto -> nuova installazione, senno' e' un aggiornamento della installazione..
  //..che sta in _strDestinationPath
  if (_strDestinationPath.IsEmpty())
  {
    wxWizardPageSimple::Chain(m_pPage[3], m_pPage[4]);  //installazione nuova
  }
  else
  {
    wxWizardPageSimple::Chain(m_pPage[3], m_pPage[8]);  //aggiornamento
  }
}
const wxString& CampoWizard::GetDestinationPath() const
{
  return _strDestinationPath;
}
void CampoWizard::SetInstallationType(const unsigned int type)
{
  _uInstallationType = type;
  //in base al tipo di installazione spara l'utente alla pagina corretta
  switch (_uInstallationType)
  {
  case 1: //server
    wxWizardPageSimple::Chain(m_pPage[4], m_pPage[6]);  //manda l'utente alla pagina server
    wxWizardPageSimple::Chain(m_pPage[6], m_pPage[8]);  //dal server alla pagina riassuntiva
    break;
  case 2: //client
    wxWizardPageSimple::Chain(m_pPage[4], m_pPage[7]);  //manda l'utente alla pagina client
    wxWizardPageSimple::Chain(m_pPage[7], m_pPage[8]);  //dal client alla pagina riassuntiva
    break;
  case 3: //aggiornamento installazione precedente
    wxWizardPageSimple::Chain(m_pPage[3], m_pPage[8]);  //manda l'utente alla pagina riassuntiva
    break;
  default:  //standard
    wxWizardPageSimple::Chain(m_pPage[4], m_pPage[5]);  //manda l'utente alla pagina standard
    wxWizardPageSimple::Chain(m_pPage[5], m_pPage[8]);  //dalla standard alla pagina riassuntiva
    break;
  }
}
const unsigned int CampoWizard::GetInstallationType() const
{
  return _uInstallationType;
}
void CampoWizard::SetPrgLocPath(const wxString& strPrgLocPath)
{
  _strPrgLocPath = strPrgLocPath;
}
const unsigned int CampoWizard::GetDongleType() const
{
  return _uDongleType;
}
void CampoWizard::SetDongleType(const unsigned int uType)
{
  _uDongleType = uType;
}
const wxString& CampoWizard::GetPrgLocPath() const
{
  return _strPrgLocPath;
}
void CampoWizard::SetPrgNetPath(const wxString& strPrgNetPath)
{
  _strPrgNetPath = strPrgNetPath;
}
const wxString& CampoWizard::GetPrgNetPath() const
{
  return _strPrgNetPath;
}
void CampoWizard::SetDataPath(const wxString& strDataPath)
{
  _strDataPath = strDataPath;
}
const wxString& CampoWizard::GetDataPath() const
{
  return _strDataPath;
}
void CampoWizard::SetInstUseAuth(const bool bInstUseAuth)
{
  _bInstUseAuth = bInstUseAuth;
}
const bool CampoWizard::GetInstUseAuth() const
{
  return _bInstUseAuth;
}
void CampoWizard::SetSrvAuth(const wxString& strSrvAuth)
{
  _strSrvAuth = strSrvAuth;
}
const wxString& CampoWizard::GetSrvAuth() const
{
  return _strSrvAuth;
}
void CampoWizard::SetInstUseDict(const bool bInstUseDict)
{
  _bInstUseDict = bInstUseDict;
}
const bool CampoWizard::GetInstUseDict() const
{
  return _bInstUseDict;
}
void CampoWizard::SetSrvDict(const wxString& strSrvDict)
{
  _strSrvDict = strSrvDict;
}
const wxString& CampoWizard::GetSrvDict() const
{
  return _strSrvDict;
}
void CampoWizard::SetSrvAutostartMode(const int iSrvAutostartMode)
{
  _iSrvAutostartMode = iSrvAutostartMode;
}
const int CampoWizard::GetSrvAutostartMode() const
{
  return _iSrvAutostartMode;
}
void CampoWizard::SetInstDemoData(const bool bInstDemoData)
{
  _bInstDemoData = bInstDemoData;
}
const bool CampoWizard::GetInstDemoData() const
{
  return  _bInstDemoData;
}
void CampoWizard::SetDesktopShortcut(const bool bDesktopShortcut)
{
  _bDesktopShortcut = bDesktopShortcut;
}
const bool CampoWizard::GetDesktopShortcut() const
{
  return  _bDesktopShortcut;
}
//...fine litania metodi di passaggio valori tra le finestre
CampoWizard::CampoWizard(wxWindow* pParent)
{
  //resettatore dei booleans (che senno' prendono valore casuale ad ogni esecuzione)
  _bInstDemoData = false;      //installa dati dimostrativi
  _bInstUseAuth = false;       //installa/usa server authoriz
  _bInstUseDict = false;       //installa/usa server diction
  _bDesktopShortcut = false;   //creazione link sul desktop
  wxBitmap bitmap;
  wxString strName = wxT("logo.gif");
  bitmap.LoadFile(strName, wxBITMAP_TYPE_GIF);
  Create(pParent, wxID_ANY, APPNAME, bitmap);
  m_pPage[0] = new CampoWizardPage1(this);   //benvenuto con logo
  m_pPage[1] = new CampoWizardPage2(this);   //scelta aggiornamento/tipo installazione
  m_pPage[2] = new CampoWizardPage3(this);   //licenza
  m_pPage[3] = new CampoWizardPage4(this);   //test ed installazione chiavi
  m_pPage[4] = new CampoWizardPage5(this);   //selezione tipo installazione
  m_pPage[5] = new CampoWizardPage6(this);   //installazione standard
  m_pPage[6] = new CampoWizardPage7(this);   //installazione server
  m_pPage[7] = new CampoWizardPage8(this);   //installazione client
  m_pPage[8] = new CampoWizardPage9(this);   //creazione icona sul desktop e in start/programmi/campo
  m_pPage[9] = new CampoWizardPage10(this);  //riassuntino installazione
  for (int p = 1; p < m_nPages; p++)
    wxWizardPageSimple::Chain(m_pPage[p-1], m_pPage[p]);
  GetPageAreaSizer()->Add(m_pPage[0]);
}
///////////////////////////////////////////////////////////
//  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()/8;
  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;
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()
  void OnTimer(wxTimerEvent& e);
  bool CreateIcon(unsigned int csidl, const wxFileName& strExeFile) const;
  bool CreateAutostartMode(const int iSrvAutostartMode, const wxString& strPath);
  void AssociateExtension(const wxFileName& strExeFile, const wxString strExt);
  
  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;
  void CheckAndMakeDir(const wxString& strDir, const wxString& strMsg) 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);
}
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);
    }
    break;
  default:
    break;
  }
  return true;
}
bool CampoSetup::CreateIcon(unsigned int csidl, const wxFileName& strExeFile) 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 strLnk;
        if (csidl == CSIDL_COMMON_STARTUP)
          strLnk.Assign(strDesktopPath, wxT("Lurch.lnk"));
        else
          strLnk.Assign(strDesktopPath, wxT("Campo.lnk"));
        // Save the link by calling IPersistFile::Save.
        wxString stringa = strLnk.GetFullPath();
        wchar_t buff[_MAX_PATH];
        memset(buff, 0, sizeof(buff));
        wxConvLocal.MB2WC(buff, stringa, stringa.Len());
        hres = ppf->Save(buff, true); 
        ppf->Release(); 
      } 
      psl->Release();
    } 
    CoUninitialize();
  }
  return true;
}
void CampoSetup::CheckAndMakeDir(const wxString& strDir, const wxString& strMsg) const
{
  if (!wxDir::Exists(strDir))
  {
    const wxFileName fname(strDir + "\\*.*");
    const wxArrayString& asDirs = fname.GetDirs();
    wxString strCartella = fname.GetVolume();
    strCartella += fname.GetVolumeSeparator();
    for (size_t i = 0; i < asDirs.GetCount(); i++)
    {
      strCartella += "\\";
      strCartella += asDirs[i];
      if (!wxDir::Exists(strCartella) && !wxMkdir(strCartella))
      {  
        wxString strError = "Impossibile creare la cartella dei ";
        strError += strMsg;
        strError += " ";
        strError += strCartella;
        strError += "\nAssicurarsi di avere il permesso di scrittura sul disco e che vi sia spazio a sufficienza";
        ErrorBox(strMsg);
        return;
      }
    }
  }
  wxDir dirDir(strDir);
  if(dirDir.HasFiles()) //se la dir di destinazione dovesse esistere gia' (installazione abortita) almeno sia vuota
  {
    ErrorBox("La cartella di destinazione non e' vuota!\nInstallazione interrotta!");
    return;
  }
}
//metodo principale dell'applicazione che gestisce l'ordine degli eventi nella installazione vera e propria
void CampoSetup::OnTimer(wxTimerEvent& WXUNUSED(e))
{
  CampoWizard* pWizard = new CampoWizard(m_pMainFrame);
  if (pWizard->Run())
  {
    wxFileName strPath = argv[0];
    strPath.SetCwd();
    //tipo di installazione/aggiornamento
    const unsigned int uInstallationType = pWizard->GetInstallationType();
    const bool bNewInstallation = uInstallationType < 3;
    //installazione servers?
    const bool bInstallLurch = uInstallationType == 1 && (pWizard->GetInstUseAuth() | pWizard->GetInstUseDict());
    //cartelle selezionate dall'utente
    const wxString& strPrgLocPath = pWizard->GetPrgLocPath();
    const wxString& strDataPath = 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");
    }
    //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(wxGetCwd(), "*.*");
    strSourcePath.AppendDir("..");
    strSourcePath.AppendDir(APPNAME);
    strSourcePath.MakeAbsolute();
    //..contando anche quanti sono e memorizzandoli in un array asFileList
    const size_t uFilesToCopy = wxDir::GetAllFiles(strSourcePath.GetPath(), &asFilesList);
    //per ogni files da copiare controlla i path sorgente e destinazione(problema con sottodirectory tipo dati)
    wxString strFileCurr;
    const size_t nPathLenght = strSourcePath.GetPath().Len();
    for (size_t i = 0; i < uFilesToCopy; i++)
    {
/*    che fare con i servers? copiare la directory comunque o saltarli?   
      if (asFilesList[i].Lower().Find("\\servers\\") > 0 && bInstallLurch)
      {
        strFileCurr = strPrgLocPath;
        strFileCurr += asFilesList[i].Mid(nPathLenght);
      }
      else*/
      //files dei dati standard! solo in caso di nuova installazione!!
      if (asFilesList[i].Lower().Find("\\dati\\") > 0)
      {
        if (bNewInstallation)  //i DATI NON VANNO MAI installati in caso di aggiornamento!!!
        {
          strFileCurr = strDataPath;
          strFileCurr += asFilesList[i].Mid(nPathLenght + 5);
        }
      }
      else  //files dei programmi
      {
        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())
      {
        strFileCurr.MakeLower();  //minuscolizzazione di sicurezza
        const wxFileName strFileName(strFileCurr);
        //i files .ini vanno trattati con i guanti (se esistono gia' non vanno copiati!!!)
        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())
            continue;
        }
        //eventuali sottodirectory le crea (solo se hanno un nome)
        const wxString strDir = strFileName.GetPath();
        if (!strDir.IsEmpty() && !wxDirExists(strDir))
          wxMkdir(strDir);
        if(!wxCopyFile(asFilesList[i], strFileCurr))
        {
          wxString strErr = "Impossibile copiare il file ";
          strErr += asFilesList[i];
          strErr += " in ";
          strErr += strFileCurr;
          strErr += "\nInstallazione interrotta!";
          ErrorBox(strErr);
          break;
        }
      } //if (!strFileCurr.IsEmpty()..
    } //for(size_t...
    
    //adesso deve compilare il campo.ini se nuova installazione..
    if (bNewInstallation)
    {
      //paragrafo [Main]
      CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main");
      const unsigned int uDongleType = pWizard->GetDongleType();
      CampoIniMain.Set("Dongle", uDongleType);
      CampoIniMain.Set("Study", strDataPath);
      CampoIniMain.Set("Firm", "com");
      //client o non client?
      if (uInstallationType == 2) //client
      {
        CampoIniMain.Set("TestDatabase", "N");
        CampoIniMain.Set("TestPrograms", "X");
      }
      else    //altri (standard,server)
      {
        CampoIniMain.Set("TestDatabase", "X");
        CampoIniMain.Set("TestPrograms", "N");
      }
      //paragrafo [Server]
      if (bInstallLurch)
      {
        CampoIniFile CampoIniSrv(strPrgLocPath + "/campo.ini", "Server");
        if (pWizard->GetInstUseAuth())
          CampoIniSrv.Set("Authoriz", pWizard->GetSrvAuth());
        if (pWizard->GetInstUseDict())
          CampoIniSrv.Set("Dictionary", pWizard->GetSrvDict());
      }
    }
    //..e modificare comunque l'install.ini aggiornando eventualmente l'origine dei programmi
    CampoIniFile CampoInstall(strPrgLocPath + "/install.ini", "Main");
    if (uInstallationType == 2) //client: directory origine sul server
      CampoInstall.Set("DiskPath", pWizard->GetPrgNetPath());
    else  //e' il path assoluto dell'install.ini che sta in 'program' (es. D:\program)
    {
      wxFileName strSourcePath(wxGetCwd());
      strSourcePath.AppendDir("program");
      strSourcePath.MakeAbsolute();
      const wxString strSrc = strSourcePath.GetPath();
      CampoInstall.Set("DiskPath", strSrc);
    }
    
    //solo se sta installando campo in postazione server e deve installare un gestore di servizi..
    //..avvia la procedura della creazione dell'autostart(un casino)
    if (bInstallLurch)
    {
      const int iSrvAutostartMode = pWizard->GetSrvAutostartMode();
      CreateAutostartMode(iSrvAutostartMode, strPrgLocPath);
    }
    
    //creazione dell'icona sul desktop
    const wxFileName strExe(strPrgLocPath, wxT("ba0.exe"));
    const bool bDesktopShortcut = pWizard->GetDesktopShortcut();
    if (bDesktopShortcut)
      CreateIcon(CSIDL_COMMON_DESKTOPDIRECTORY, strExe);
    //  1)  terminato il tutto scrive/aggiorna/lascia stare il campo.stp
    if (bNewInstallation)
    {
      CampoIniFile CampoStp("C:\\campo.stp", "");
    }
    //  2)  procede poi al caricamento delle patch eventuali di sistema all'interno della dir 'program'
    //la procedura di unzippamento dovrebbe essere quella di ba1.exe
    //  3)  riaggiorna eventualmente il livello versione/patch del SY in install.ini
    //  4)  lanciare ba1.exe -6 in uscita (non va qui! e' solo per ricordarsi di farlo!)
    //questo e' un esempio di associazione automatica di estensione file
    //if (pWizard->GetBool(bAssocExtension))
    //  AssociateExtension(strExe, wxT(".caz"));
  }
  pWizard->Destroy();
  ::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;
}