Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunto comandi di attivazione remota di assistenza, moduli e utenti git-svn-id: svn://10.65.10.50/branches/R_10_00@21360 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			972 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			972 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| /////////////////////////////////////////////////////////////////////////////
 | |
| // Name:        BaseServ.cpp
 | |
| // Purpose:     Simple base Server
 | |
| // Author:      Guy
 | |
| // Modified by:
 | |
| // Created:     21/08/2002
 | |
| // Copyright:   (c) 2002 Guy
 | |
| // Licence:     wxWindows licence
 | |
| /////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // ==========================================================================
 | |
| // declarations
 | |
| // ==========================================================================
 | |
| 
 | |
| // --------------------------------------------------------------------------
 | |
| // headers
 | |
| // --------------------------------------------------------------------------
 | |
| #include <wx/wx.h>
 | |
| #include "baseserv.h"
 | |
| 
 | |
| #include <wx/config.h>
 | |
| #include <wx/filename.h>
 | |
| #include <wx/image.h>
 | |
| #include <wx/mimetype.h>
 | |
| #include <wx/mstream.h>
 | |
| #include <wx/sckstrm.h>
 | |
| #include <wx/tokenzr.h>
 | |
| 
 | |
| #ifndef __WXMSW__
 | |
| #include <wx/fileconf.h>
 | |
| #endif
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Utilities
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| IMPLEMENT_ABSTRACT_CLASS(TBaseServerApp, wxApp)
 | |
| 
 | |
| TBaseServerApp& GetServerApp()
 | |
| {	return *wxStaticCast(wxTheApp, TBaseServerApp); }
 | |
| 
 | |
| wxString Date2String(const wxDateTime& date)
 | |
| {	return date.Format("%d-%m-%Y"); }
 | |
| 
 | |
| wxDateTime String2Date(const wxString& str)
 | |
| {
 | |
| 	int d, m, y;
 | |
| 	sscanf(str, "%d-%d-%d", &d, &m, &y);
 | |
| 	wxDateTime date(d, wxDateTime::Month(m-1), y);
 | |
| 	return date;
 | |
| }
 | |
| 
 | |
| wxSocketBase& operator<<(wxSocketBase& outf, const wxChar* str)
 | |
| {
 | |
| 	if (str && *str)
 | |
|     outf.Write(str, (wxUint32)wxStrlen(str));
 | |
| 	return outf;
 | |
| }
 | |
| 
 | |
| wxSocketBase& operator<<(wxSocketBase& outf, wxString str)
 | |
| {
 | |
| 	if (!str.IsEmpty())
 | |
|     outf.Write(str, (wxUint32)str.Length());
 | |
| 	return outf;
 | |
| }
 | |
| 
 | |
| wxSocketBase& operator<<(wxSocketBase& outf, size_t num)
 | |
| {	return outf << wxString::Format("%u", num); }
 | |
| 
 | |
| // --------------------------------------------------------------------------
 | |
| // classes
 | |
| // --------------------------------------------------------------------------
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // THashTable
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| void THashTable::Put(const wxString& key, const wxString& value)
 | |
| {
 | |
| 	THashString* entry = new THashString(value);
 | |
| 	m_Hash.Put(key, entry);
 | |
| }
 | |
| 
 | |
| wxString THashTable::Get(const wxChar* key) const
 | |
| {
 | |
| 	wxString strValue;
 | |
| 	THashString* str = (THashString*)m_Hash.Get(key);
 | |
| 	if (str != NULL)
 | |
| 		strValue = str->m_str;
 | |
| 	return strValue;
 | |
| }
 | |
| 
 | |
| THashTable::THashTable(size_t size) : m_Hash(wxKEY_STRING, size) 
 | |
| { 
 | |
| 	m_Hash.DeleteContents(true); 
 | |
| }
 | |
| 
 | |
| #ifdef wxHAS_TASK_BAR_ICON
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TTaskbarIcon
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| BEGIN_EVENT_TABLE(TTaskBarIcon, wxTaskBarIcon)
 | |
|   EVT_TASKBAR_LEFT_DOWN(TTaskBarIcon::OnTaskBarClick)
 | |
| END_EVENT_TABLE()
 | |
| 
 | |
| void TTaskBarIcon::OnTaskBarClick(wxTaskBarIconEvent& WXUNUSED(e))
 | |
| {
 | |
|   wxString strURL;
 | |
| //  wxIPV4address addr; addr.AnyAddress(); 
 | |
| //  addr.Service(GetServerApp().GetDefaultPort());
 | |
| //  url << addr.Hostname() << ":" << addr.Service();
 | |
|   strURL << "http://127.0.0.1:" << GetServerApp().GetDefaultPort();
 | |
|   wxLaunchDefaultBrowser(strURL);
 | |
| }
 | |
| 
 | |
| void TTaskBarIcon::Init()
 | |
| {
 | |
|   const TBaseServerApp& a = GetServerApp();
 | |
|   wxIcon icon;
 | |
| 
 | |
|   const wxString strIcon = a.GetConfigString("Icon");
 | |
|   if (wxFileExists(strIcon))
 | |
|   {
 | |
|     wxInitAllImageHandlers();
 | |
|     wxImage img(strIcon);
 | |
|     img.Rescale(32,32/*,wxIMAGE_QUALITY_HIGH*/);
 | |
|     const wxBitmap bmp(img);
 | |
|     icon.CopyFromBitmap(bmp);
 | |
|   }
 | |
|   else
 | |
|     icon.LoadFile("soap", wxBITMAP_TYPE_ICO_RESOURCE);
 | |
| 
 | |
|   SetIcon(icon, a.GetAppName());
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TBaseServerApp
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| enum 
 | |
| {
 | |
|   SERVER_ID = 1001,
 | |
|   SOCKET_ID = 1002,
 | |
|   DATAGRAM_ID = 1003,
 | |
| };
 | |
| 
 | |
| 
 | |
| BEGIN_EVENT_TABLE(TBaseServerApp, wxApp)
 | |
|   EVT_SOCKET(SERVER_ID, TBaseServerApp::OnServerEvent)
 | |
|   EVT_SOCKET(SOCKET_ID, TBaseServerApp::OnSocketEvent)
 | |
|   EVT_SOCKET(DATAGRAM_ID, TBaseServerApp::OnDatagramEvent)
 | |
|   EVT_IDLE(TBaseServerApp::OnIdle)
 | |
| END_EVENT_TABLE()
 | |
| 
 | |
| void TBaseServerApp::WriteLog(const wxChar* str, int nPriority) const
 | |
| {
 | |
|   const bool doit = (m_log != NULL) && (m_bLogVerbose || nPriority > 0);
 | |
| 	if (doit)
 | |
|   {
 | |
|     //raccatta data ed ora
 | |
|     const wxString strNow = wxNow();
 | |
| 	  *m_log << strNow << " " << str << endl;
 | |
|   }
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::GetTempFilename(const wxChar * ext)
 | |
| {
 | |
| 	wxString strTmp;
 | |
| 	if (m_strTempDir.IsEmpty())
 | |
| 	{
 | |
|     const wxString strPrefix = "Srv";
 | |
|     ::wxGetTempFileName(strPrefix, strTmp);
 | |
| 		::wxRemoveFile(strTmp);
 | |
| 		(wxString&)m_strTempDir << ::wxPathOnly(strTmp) << "/";
 | |
| 	}
 | |
| 	strTmp = m_strTempDir;
 | |
|   strTmp += wxString::Format("%s_%d.%s", GetAppName(), m_nTmpCounter, ext);
 | |
|   m_nTmpCounter++;
 | |
| 	if (m_nTmpCounter >= 32)
 | |
| 		m_nTmpCounter = 0;
 | |
| 
 | |
| 	return strTmp;
 | |
| }
 | |
| 
 | |
| TXmlItem& TBaseServerApp::AddLogo(TXmlItem& tr) const 
 | |
| {
 | |
| 	TXmlItem& td = tr.AddChild("td");
 | |
| 	td.SetAttr("width", "15%");
 | |
| 	td.SetAttr("align", "center");
 | |
| 	
 | |
| 	TXmlItem& a = td.AddChild("a");
 | |
| 	a.SetAttr("href", "/index.htm");
 | |
|   
 | |
| 	const wxString gif = GetConfigString("Icon", "euro.gif");
 | |
| 	TXmlItem& img = a.AddChild("img");
 | |
| 	img.SetAttr("src", gif);
 | |
| 	img.SetAttr("border", "0");
 | |
| 	img.SetAttr("alt", "Return to Home Page");
 | |
| 	
 | |
| 	return td;
 | |
| }
 | |
| 
 | |
| TXmlItem& TBaseServerApp::CreatePageBody(TXmlItem& html, wxString header) const
 | |
| {
 | |
|   if (header.IsEmpty())
 | |
| 		header << GetAppName() << " Server";
 | |
| 
 | |
| 	html.SetTag("html");
 | |
| 	
 | |
| 	TXmlItem& head = html.AddChild("head");
 | |
|   TXmlItem& meta1 = head.AddChild("meta");
 | |
| 	meta1.SetAttr("name", "GENERATOR"); 
 | |
| 	meta1.SetAttr("content", GetAppName());
 | |
|   TXmlItem& meta2 = head.AddChild("meta");
 | |
| 	meta2.SetAttr("HTTP-EQUIV", "Content-Type"); 
 | |
| 	meta2.SetAttr("content", "text/html; charset=iso-8859-1");
 | |
|   head.AddChild("title") << header;
 | |
| 
 | |
| 	TXmlItem& body = html.AddChild("body");
 | |
| 	body.SetAttr("bgcolor", "#EFCEAD");
 | |
| 	if (IsRunning())
 | |
|   	body.SetAttr("background", "back.gif");
 | |
| 
 | |
| 	TXmlItem& title = body.AddChild("table");
 | |
| 	title.SetAttr("border", "5"); title.SetAttr("width", "100%");
 | |
| 	TXmlItem& title_tr = title.AddChild("tr");
 | |
| 
 | |
| 	if (IsRunning())
 | |
|     AddLogo(title_tr);
 | |
|   
 | |
| 	TXmlItem& td1 = title_tr.AddChild("td");
 | |
| 	td1.AddChild("h1").AddChild("center") << header;
 | |
| 	
 | |
| 	if (IsRunning())
 | |
|     AddLogo(title_tr);
 | |
|   
 | |
| 	body.AddChild("br");
 | |
| 	return body;
 | |
| }
 | |
| 
 | |
| TXmlItem& TBaseServerApp::AddLinkButton(TXmlItem& body, const wxChar* strCaption, const wxChar* strHref) const
 | |
| {
 | |
|   /*
 | |
|   TXmlItem& table = body.AddChild("table");
 | |
| 	table.SetAttr("border", "2"); table.SetAttr("bgcolor", "#C0C0C0");
 | |
| 
 | |
| 	TXmlItem& td = table.AddChild("tr").AddChild("td");
 | |
| 	td.SetAttr("align", "center");
 | |
| 	td.AddChild("a").SetAttr("href", strHref) << strCaption;
 | |
| 	return table;
 | |
|   */
 | |
| 
 | |
|   TXmlItem& b = body.AddChild("button");
 | |
| 	b.SetAttr("type", "button"); 
 | |
|   wxString strScript;
 | |
|   strScript += "window.open('";
 | |
|   strScript += strHref;
 | |
|   strScript += "', '_self')";
 | |
|   b.SetAttr("onClick", strScript); 
 | |
|   b << strCaption;
 | |
| 	return b;
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::MessageBox(const wxChar* caption, const wxChar* msg, wxSocketBase& outs)
 | |
| {
 | |
|   TXmlItem html; 
 | |
| 	TXmlItem& body = CreatePageBody(html); 
 | |
| 
 | |
| 	TXmlItem& table = body.AddChild("center").AddChild("table");
 | |
| 	table.SetAttr("width", "70%"); table.SetAttr("border", "2");
 | |
| 	table.AddChild("caption").AddChild("h2") << caption;
 | |
| 
 | |
| 	TXmlItem& td0 = table.AddChild("tr").AddChild("td");
 | |
| 	td0.SetAttr("align", "justify");
 | |
| 	td0.AddChild("h3") << msg;
 | |
| 
 | |
|   if (m_bRunning) // Aggiungi il bottone di ritorno solo se il server non si sta spegnendo
 | |
|   {
 | |
| 	  TXmlItem& td1 = table.AddChild("tr").AddChild("td");
 | |
| 	  td1.SetAttr("align", "center");
 | |
| 	  AddLinkButton(td1, _("Return to main page"), "index.htm");
 | |
|   }
 | |
| 
 | |
| 	const wxString strTmp = GetTempFilename();
 | |
| 	html.Save(strTmp);
 | |
| 	SendFile(strTmp, outs);
 | |
| }
 | |
| 
 | |
| bool TBaseServerApp::CanProcessCommand(wxString& cmd, wxSocketBase& outs)
 | |
| {
 | |
| 	if (cmd.Find("stop.cgi") >= 0)
 | |
| 	{
 | |
| 	  m_bRunning = false; // Disable gif on title
 | |
| 		if (outs.IsOk())
 | |
| 			MessageBox("Warning!", "Server Stopped", outs);
 | |
|     ExitMainLoop();
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::SendContent(wxFileInputStream& inf, wxSocketBase& sock)
 | |
| {
 | |
| 	const size_t nSize = inf.GetSize();
 | |
|   WriteLog(wxString::Format("Sending %lu bytes", nSize), 0);
 | |
| 
 | |
| 	const size_t BUF_TEMP_SIZE = 1024*1024;  // was 1024*16
 | |
|   char* buf = new char[BUF_TEMP_SIZE];
 | |
|   size_t bytes = BUF_TEMP_SIZE;
 | |
| 	size_t nTotalWritten = 0;
 | |
|   while (bytes == BUF_TEMP_SIZE)
 | |
|   {
 | |
|     bytes = inf.Read(buf, bytes).LastRead();
 | |
|     size_t nWritten = sock.Write(buf, wxUint32(bytes)).LastCount();
 | |
| 		nTotalWritten += nWritten;
 | |
|   }
 | |
| 	delete buf;
 | |
| 
 | |
| 	if (nTotalWritten < nSize)
 | |
| 		WriteLog(wxString::Format("I sent %lu of %lu bytes only.", nTotalWritten, nSize), 1);
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::SendFile(wxString strFilename, wxSocketBase& sock)
 | |
| {
 | |
|   const bool bFound = wxFileExists(strFilename);
 | |
| 	if (!bFound)
 | |
| 	{
 | |
| 		const wxString strTmp = GetTempFilename();
 | |
| 		if (!strTmp.IsEmpty())
 | |
| 		{
 | |
| 			TXmlItem html; 
 | |
| 			TXmlItem& body = CreatePageBody(html); 
 | |
| 			body.AddChild("h1") << "Sorry: File not found!";
 | |
| 			body.AddChild("br");
 | |
| 			body.AddChild("h2") << strFilename;
 | |
| 			html.Save(strTmp);
 | |
| 		}
 | |
|  		strFilename = strTmp;
 | |
| 	}
 | |
| 
 | |
| 	wxString strType;
 | |
| 	wxSplitPath(strFilename, NULL, NULL, &strType);
 | |
| 	wxFileType* type = wxTheMimeTypesManager->GetFileTypeFromExtension(strType);
 | |
| 	if (type != NULL)
 | |
| 		type->GetMimeType(&strType);
 | |
| 	else
 | |
| 		strType = "text/plain";
 | |
| 	const wxDateTime date = ::wxFileModificationTime(strFilename);
 | |
| 
 | |
| 	wxFileInputStream inf(strFilename);
 | |
| 	const size_t nSize = inf.GetSize();
 | |
| 
 | |
| 	if (bFound)
 | |
| 	  sock << "HTTP/1.1 200 OK\n";
 | |
| 	else
 | |
|     sock << "HTTP/1.1 401 Not found\n";
 | |
| 	sock << "Server: " << GetAppName() << "\n";
 | |
| 	sock << "Host: " << wxGetFullHostName() << "\n";
 | |
| 	if (bFound && m_bRunning)
 | |
| 	  sock << "Connection: keep-alive\n";
 | |
| 	else
 | |
| 		sock << "Connection: close\n";
 | |
| 	sock << "Content-Type: " << strType << "\n";
 | |
|  	sock << "Content-Length: " << nSize << "\n";
 | |
| 	sock << "Date: " << date.Format("%#c") << "\n";
 | |
| 
 | |
|   wxDateTime dtFraUnPo = wxDateTime::Now();
 | |
| 	const wxTimeSpan minuto(0, 1, 0);  // Zero ore, Un minuto, Zero secondi
 | |
| 	dtFraUnPo += minuto;
 | |
|   sock << "Expires: " << dtFraUnPo.Format("%#c") << "\n";
 | |
| 
 | |
|   sock << "\n";
 | |
| 
 | |
|   SendContent(inf, sock);  
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::SoapProcessMethod(const TXmlItem& WXUNUSED(xmlMethod), TXmlItem& WXUNUSED(xmlAnswer))
 | |
| {
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::ProcessSoapCommand(wxString cmd, wxSocketBase& sock)
 | |
| {
 | |
| 	TXmlItem xmlEnvelope;
 | |
| 	xmlEnvelope.SetTag("SOAP-ENV:Envelope");
 | |
| 	TXmlItem& xmlBody = xmlEnvelope.AddChild("SOAP-ENV:Body");
 | |
| 
 | |
| 	const int soapstart = cmd.Find("<SOAP-ENV:");
 | |
| 	if (soapstart > 0)
 | |
| 	{
 | |
| 		const size_t soaplen = cmd.length() - soapstart;
 | |
| 		const char* buff = (const char*)cmd;
 | |
| 		buff += soapstart;
 | |
| 		wxMemoryInputStream input(buff, soaplen);
 | |
| 		TXmlItem query; 
 | |
| 		if (query.Read(input))
 | |
| 		{
 | |
| 			const TXmlItem* pxmlBody = query.FindFirst("SOAP-ENV:Body");
 | |
| 			if (pxmlBody != NULL) for (int m = 0; ; m++)
 | |
| 			{
 | |
| 				const TXmlItem* pxmlMethod = pxmlBody->GetChild(m);
 | |
| 				if (pxmlMethod == NULL)
 | |
| 					break;
 | |
| 				if (pxmlMethod->GetTag().StartsWith("m:"))
 | |
| 				{
 | |
| 					wxString str = pxmlMethod->GetTag(); str += "Result";
 | |
| 					TXmlItem& xmlAnswer = xmlBody.AddChild(str);
 | |
| 					SoapProcessMethod(*pxmlMethod, xmlAnswer);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	const wxString strResult = xmlEnvelope.AsString();
 | |
|   
 | |
| 	sock << "HTTP/1.1 200 OK" << endl;
 | |
| 	sock << "Connection: keep-alive" << endl;
 | |
| 	sock << "Content-Length: " << strResult.Length() << endl;
 | |
| 	sock << "Content-Type: text/xml; charset=utf-8" << endl;
 | |
| 	sock << "Date: " << wxDateTime::Now().Format("%#c") << endl;
 | |
| 	sock << "Server: " << GetAppName() << endl;
 | |
|   sock << "Host: " << wxGetFullHostName() << endl;
 | |
| 	sock << endl;
 | |
| 	sock << strResult;
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::ProcessHttpGet(wxString cmd, wxSocketBase& sock)
 | |
| {
 | |
|   const int stop = cmd.Find(" HTTP");
 | |
| 	wxString str = cmd.Mid(4, stop-4).Trim();
 | |
| 
 | |
|   if (str == "/")
 | |
| 	  str += "index.htm";
 | |
|   wxString strFilename = GetDocumentRoot() + str;
 | |
|   SendFile(strFilename, sock);
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::ProcessFormCommand(wxString WXUNUSED(cmd), 
 | |
|                                         wxSocketBase& WXUNUSED(sock))
 | |
| { }
 | |
| 
 | |
| void TBaseServerApp::SendNotModifiedFile(wxSocketBase& sock)
 | |
| {
 | |
| 	sock << "HTTP/1.1 304 Not Modified\n";
 | |
| 	sock << "Date: " << wxDateTime::Now().Format("%#c") << "\n";
 | |
|   sock << "Server: " << GetAppName() << "\n";
 | |
|   sock << "Connection: close\n";
 | |
| }
 | |
| 
 | |
| const wxChar* TBaseServerApp::GetAppName() const
 | |
| {
 | |
| 	// Pure virtual function
 | |
| 	return "Server";
 | |
| }
 | |
| 
 | |
| bool TBaseServerApp::ProcessCommand(wxString cmd, wxSocketBase& outs)
 | |
| {
 | |
|   WriteLog(cmd, 0);
 | |
| 
 | |
|   bool bProcessed = true;
 | |
|   if (cmd.StartsWith("POST "))
 | |
| 	{
 | |
|     if (cmd.Find("SOAPAction") > 0)
 | |
| 			ProcessSoapCommand(cmd, outs);
 | |
| 		else
 | |
|       ProcessFormCommand(cmd, outs);
 | |
| 	} else
 | |
|   if (cmd.StartsWith("GET "))
 | |
| 		ProcessHttpGet(cmd, outs); else
 | |
|   if (cmd.StartsWith("PING"))
 | |
|     outs << "PONG\n";
 | |
|   else
 | |
|     bProcessed = false;
 | |
|   return bProcessed;
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::OnServerEvent(wxSocketEvent& e)
 | |
| {
 | |
|   // Accept new connection if there is one in the pending
 | |
|   // connections queue, else exit. We use Accept(FALSE) for
 | |
|   // non-blocking accept (although if we got here, there
 | |
|   // should ALWAYS be a pending connection).
 | |
| 
 | |
|   switch(e.GetSocketEvent())
 | |
|   {
 | |
|   case wxSOCKET_CONNECTION:
 | |
|     {
 | |
|       wxSocketBase* sock = m_server->Accept(false);
 | |
|       if (sock != NULL)
 | |
|       {
 | |
|         sock->SetEventHandler(*this, SOCKET_ID);
 | |
|         sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
 | |
|         sock->Notify(true);
 | |
|         WriteLog(_("Connection accepted."));
 | |
|       }
 | |
|       else
 | |
|         WriteLog(_("Connection REFUSED!"), 1);
 | |
|     }
 | |
|     break;
 | |
|   default:
 | |
|     WriteLog(_("Unhandled server event!"), 1);
 | |
|     break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| struct TCommand : public wxObject
 | |
| {
 | |
| 	wxSocketBase* m_Sock;
 | |
| 	wxString m_Command;
 | |
| };
 | |
| 
 | |
| void TBaseServerApp::OnSocketEvent(wxSocketEvent& e)
 | |
| {
 | |
|   wxSocketBase* sock = e.GetSocket();
 | |
|   switch(e.GetSocketEvent())
 | |
|   {
 | |
|   case wxSOCKET_INPUT:
 | |
|     if (sock != NULL && sock->IsOk())
 | |
|     {
 | |
|       // We disable input events, so that the test doesn't trigger wxSocketEvent again.
 | |
|       sock->SetNotify(wxSOCKET_LOST_FLAG);
 | |
| 			TCommand* message = new TCommand;
 | |
| 			message->m_Sock = sock;
 | |
| 
 | |
| 		  // Read the data
 | |
| 			const size_t BUFSIZE = 1024;
 | |
| 			wxChar  buf[BUFSIZE + 16];
 | |
| 			memset(buf, 0, sizeof(buf));
 | |
| 			while (sock->Read(buf, BUFSIZE).LastCount() == BUFSIZE)
 | |
| 			{
 | |
| 				message->m_Command << buf;
 | |
| 				memset(buf, 0, sizeof(buf));
 | |
| 			}
 | |
| 			message->m_Command << buf;
 | |
| 			m_Sockets.Add(message);
 | |
| 
 | |
|       // Enable input events again.
 | |
|       sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
 | |
|     }
 | |
|     break;
 | |
|   case wxSOCKET_LOST:
 | |
|     WriteLog(_("--- Socket lost."), 0);
 | |
|     if (sock != NULL)
 | |
|     {
 | |
|       for (int i = m_Sockets.GetCount()-1; i >= 0; i--)
 | |
|       {
 | |
|         TCommand& cmd = *(TCommand*)m_Sockets[i];
 | |
|         if (cmd.m_Sock == sock)
 | |
|           m_Sockets.RemoveAt(i);
 | |
|       }
 | |
|       if (sock->IsOk())
 | |
|         sock->Destroy();
 | |
|     }
 | |
|     break;
 | |
|   default: 
 | |
|     break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::OnDatagramEvent(wxSocketEvent& WXUNUSED(e))
 | |
| {
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::OnIdle(wxIdleEvent& evt)
 | |
| {
 | |
| 	if (m_Sockets.GetCount() > 0)
 | |
| 	{
 | |
|     TCommand& cmd = *(TCommand*)m_Sockets[0];
 | |
| 	  wxSocketBase& sock = *cmd.m_Sock;
 | |
| 		const bool valid_socket = sock.IsOk();
 | |
| 		if (valid_socket)
 | |
| 			sock.SetNotify(wxSOCKET_LOST_FLAG);
 | |
| 
 | |
| 		wxString& str = cmd.m_Command;
 | |
| 
 | |
| 		if (CanProcessCommand(str, sock))
 | |
| 		{
 | |
| 			if (valid_socket)
 | |
|       {
 | |
|   			const wxSocketFlags flags = sock.GetFlags();
 | |
| 				sock.SetFlags(wxSOCKET_WAITALL);
 | |
| 	  		ProcessCommand(str, sock);
 | |
| 				sock.SetFlags(flags);
 | |
|       }
 | |
|       else
 | |
|         ProcessCommand(str, sock); // Comandi come "UserLogout" vanno processati anche per socket non validi
 | |
| 		}
 | |
| 
 | |
| 		// Enable input events again.
 | |
| 
 | |
| 		if (valid_socket)
 | |
| 		{
 | |
| 			sock.SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
 | |
| 		  sock.Notify(true);
 | |
| 		}
 | |
| 
 | |
| 		m_Sockets.RemoveAt(0);
 | |
|     evt.RequestMore(); // FONDAMENTALE per gestire richieste multiple!
 | |
| 	}
 | |
| 	wxApp::OnIdle(evt);
 | |
| }
 | |
| 
 | |
| const wxString& TBaseServerApp::GetConfigName() const
 | |
| {
 | |
|   if (m_strIni.IsEmpty())
 | |
| 	{
 | |
| 	  wxFileName name(argv[0]); // Prendo il persorso completo del server in esecuzione
 | |
| 	  name.SetName("servers");  // Trasformo il nome in servers ...
 | |
| 	  name.SetExt("ini");       // ... e l'esetensione in .ini
 | |
|     name.MakeAbsolute();
 | |
| 	  (wxString&)m_strIni = name.GetFullPath();
 | |
| 	}
 | |
| 	return m_strIni;
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::GetConfigFileString(const wxChar* file, const wxChar* paragraph, const wxChar* key, const wxChar* def) const
 | |
| {
 | |
|   wxString str;
 | |
| 
 | |
|   if (file == NULL || *file <= ' ')
 | |
|     file = GetConfigName();
 | |
|   if (paragraph == NULL || *paragraph <= ' ')
 | |
|     paragraph = GetAppName();
 | |
| 
 | |
| #ifdef __WXMSW__
 | |
|   wxChar value[512]; memset(value, 0, sizeof(value));
 | |
|   const int len = ::GetPrivateProfileString(paragraph, key, def, value, sizeof(value)-1, file);
 | |
|   str = len <= 0 ? def : value;
 | |
| #else
 | |
|   wxFileConfig ini("", "", file, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
 | |
| 	str << '/' << paragraph;
 | |
| 	ini.SetPath(str);
 | |
| 	ini.Read(key, &str, def);
 | |
| #endif
 | |
| 
 | |
|   return str;
 | |
| }
 | |
| 
 | |
| long TBaseServerApp::GetConfigFileInt(const wxChar* file, const wxChar* paragraph, const wxChar* key, long val) const
 | |
| {
 | |
|   const wxString str = GetConfigFileString(file, paragraph, key, "*");
 | |
|   if (str != "*")
 | |
|     str.ToLong(&val);
 | |
|   return val;
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::SetConfigFileString(const wxChar* file, const wxChar* paragraph, const wxChar* key, const wxChar* val) const
 | |
| {
 | |
|   if (file == NULL || *file <= ' ')
 | |
| 		file = GetConfigName();
 | |
|   if (paragraph == NULL || *paragraph <= ' ')
 | |
| 		paragraph = GetAppName();
 | |
| 
 | |
| #ifdef __WXMSW__
 | |
|   ::WritePrivateProfileString(paragraph, key, val, file);
 | |
| #else
 | |
|   wxFileConfig ini("", "", file, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
 | |
| 	wxString str;
 | |
| 	str << '/' << paragraph;
 | |
| 	ini.SetPath(str);
 | |
| 	ini.Write(key, val);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app) const
 | |
| {
 | |
|   return SetConfigFileString(NULL, app, key, val);
 | |
| }
 | |
| 
 | |
| void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app) const
 | |
| {
 | |
|   wxString str; str.Printf("%d", val);
 | |
|   SetConfigString(key, str, app);
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::GetConfigString(const wxChar* key, const wxChar* def, const wxChar* app) const
 | |
| {
 | |
|   return GetConfigFileString(NULL, app, key, def);
 | |
| }
 | |
| 
 | |
| int TBaseServerApp::GetConfigInt(const wxChar* key, int def, const wxChar* app) const
 | |
| {
 | |
| 	return GetConfigFileInt(NULL, app, key, def);
 | |
| }
 | |
| 
 | |
| bool TBaseServerApp::GetConfigBool(const wxChar* key, bool def, const wxChar* app) const
 | |
| {
 | |
| 	bool val = def;
 | |
| 	const wxString str = GetConfigString(key, "*", app);
 | |
| 	if (str != "*")
 | |
| 		val = (str[0u] == '1') || (str[0u] == 'T') || (str[0u] == 'X') || (str[0u] == 'Y') || (str.CmpNoCase("On") == 0);
 | |
| 	return val;
 | |
| }
 | |
| 
 | |
| int TBaseServerApp::GetDefaultPort() const
 | |
| {	return GetConfigInt("Port", 3883); }
 | |
| 
 | |
| int TBaseServerApp::GetUDPPort() const
 | |
| { return GetConfigInt("PortUDP", 0); }
 | |
| 
 | |
| #define OEM_INI wxT("../setup/oem.ini")
 | |
| 
 | |
| int TBaseServerApp::GetOemInt(const wxChar* key, int def) const
 | |
| {
 | |
|   static int _oem = GetConfigFileInt(OEM_INI, "MAIN", "OEM", -1);
 | |
|   if (_oem >= 0)
 | |
|   {
 | |
|     if (wxStrcmp(key, wxT("OEM")) != 0)
 | |
|     {
 | |
|       wxString str; str.Printf(wxT("OEM_%d"), _oem);
 | |
|       def = GetConfigFileInt(OEM_INI, str, key, def);
 | |
|     }
 | |
|     else
 | |
|       def = _oem;
 | |
|   }
 | |
| 
 | |
|   return def;
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::GetOemString(const wxChar* key, const wxChar* def) const
 | |
| {
 | |
|   const int oem = GetOemInt("OEM", -1);
 | |
|   wxString str = def;
 | |
|   if (oem >= 0)
 | |
|   {
 | |
|     if (wxStrcmp(key, "OEM") != 0)
 | |
|     {
 | |
|       str.Printf("OEM_%d", oem);
 | |
|       str = GetConfigFileString(OEM_INI, str, key, def);
 | |
|     }
 | |
|     else
 | |
|       str.Printf("%d", oem);
 | |
|   }
 | |
|   return str;
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::GetInstallString(const wxChar* key, const wxChar* module) const 
 | |
| { 
 | |
|   if (module == NULL || *module <= ' ')
 | |
|     module = wxT("sr");
 | |
|   return GetConfigFileString(wxT("../install.ini"), module, key, wxEmptyString); 
 | |
| }
 | |
| 
 | |
| bool TBaseServerApp::IsAdvanced() const 
 | |
| { 
 | |
|   const int nOEM = GetOemInt(wxT("OEM"), -1);
 | |
|   return nOEM==0;
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::GetLogFileName() const
 | |
| { return GetConfigString("LogFile"); }
 | |
| 
 | |
| wxString TBaseServerApp::GetDocumentRoot() const
 | |
| { return GetConfigString("DocumentRoot", m_strPath); }
 | |
| 
 | |
| bool TBaseServerApp::IsRunning() const 
 | |
| { return m_bRunning && IsMainLoopRunning() && Ok(); }
 | |
| 
 | |
| bool TBaseServerApp::OnInit()
 | |
| {
 | |
|   m_server = NULL;
 | |
| 	m_datagram = NULL;
 | |
| 	m_log = NULL;
 | |
|   m_bRunning = false;
 | |
| 
 | |
|   m_SingleInstance = new wxSingleInstanceChecker(GetAppName());
 | |
|   if (m_SingleInstance->IsAnotherRunning())
 | |
| 	{
 | |
|     wxMessageBox(_("Another instance is already running"), GetAppName(), wxICON_HAND);
 | |
| 		delete m_SingleInstance;
 | |
| 		m_SingleInstance = NULL;
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	wxFileName::SplitPath(argv[0], &m_strPath, NULL, NULL);
 | |
| 	if (!m_strPath.IsEmpty())
 | |
|   {
 | |
| 		wxSetWorkingDirectory(m_strPath);
 | |
|     if (!wxEndsWithPathSeparator(m_strPath))
 | |
|       m_strPath += wxFILE_SEP_PATH;
 | |
|   }
 | |
| 
 | |
|   // Create the address - defaults to localhost:0 initially
 | |
|   wxIPV4address addr;
 | |
|   addr.AnyAddress(); // I docs affermano che AnyAddress sia meglio di LocalHost
 | |
|   const int nTCPPort = GetDefaultPort();
 | |
|   addr.Service(nTCPPort);
 | |
|   // Create the TCP socket
 | |
|   m_server = new wxSocketServer(addr);
 | |
| 
 | |
|   // Create the Log file
 | |
| 	//Prima di creare il nuovo log file (vuoto) salva quello vecchio aggiungendo al nome data e ora di ripartenza..
 | |
|   //..Serve per monitorare i defungimenti dei server
 | |
| 	const wxString strLog = GetLogFileName();
 | |
|   if (!strLog.IsEmpty())
 | |
|   {
 | |
|     wxFileName fnLogFileName(strLog);
 | |
|     if (fnLogFileName.FileExists())
 | |
|     {
 | |
|       const wxDateTime dtNow = wxDateTime::Now();
 | |
|       wxString strWorkString;
 | |
|       strWorkString.Printf("%04d%02d%02d_%02d%02d_", 
 | |
|                         dtNow.GetYear(), dtNow.GetMonth() + 1, dtNow.GetDay(), 
 | |
|                         dtNow.GetHour(), dtNow.GetMinute());
 | |
|       strWorkString << fnLogFileName.GetName();
 | |
|       fnLogFileName.SetName(strWorkString);
 | |
|       wxCopyFile(strLog, fnLogFileName.GetFullPath());
 | |
|     }
 | |
| 
 | |
|   	m_log = new wxFileOutputStream(strLog);
 | |
|     m_bLogVerbose = GetConfigBool("LogVerbose");
 | |
|   }
 | |
| 	else
 | |
|   {
 | |
| 		m_log = NULL;
 | |
|     m_bLogVerbose = false;
 | |
|   }
 | |
| 
 | |
| 	m_nTmpCounter = 0;
 | |
| 
 | |
| 	// We use Ok() here to see if the server is really listening
 | |
|   if (m_server->Ok())
 | |
|   {
 | |
| 		// Setup the event handler and subscribe to connection events
 | |
| 		m_server->SetEventHandler(*this, SERVER_ID);
 | |
| 		m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
 | |
| 		m_server->Notify(true);
 | |
| 
 | |
|     wxString str;
 | |
|     str << GetAppName() << _(" listening at ") << addr.Hostname() << wxT(":") << addr.Service();
 | |
|   	WriteLog(str);
 | |
| 
 | |
| 		m_bRunning = Initialization();
 | |
| 	}
 | |
|   else
 | |
|   {
 | |
|     wxString str;
 | |
|     str << GetAppName() << _(" could not listen to port ") << addr.Service();
 | |
|   	WriteLog(str);
 | |
|   }
 | |
| 
 | |
| #ifdef wxHAS_TASK_BAR_ICON
 | |
|   m_Tray = NULL;
 | |
|   if (m_bRunning) 
 | |
|   {
 | |
|     m_Tray = new TTaskBarIcon;
 | |
|     m_Tray->Init();
 | |
|   }
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|   // Create the UDP socket
 | |
|   const int nUDPPort = GetUDPPort();
 | |
|   if (m_bRunning && nUDPPort > nTCPPort)
 | |
|   {
 | |
|     wxIPV4address udp_addr;
 | |
|     udp_addr.AnyAddress(); // I docs affermano che AnyAddress sia meglio di LocalHost
 | |
|     udp_addr.Service(nUDPPort);
 | |
|     m_datagram = new wxDatagramSocket(udp_addr);
 | |
| 
 | |
| 		// Setup the event handler and subscribe to connection events
 | |
| 		m_datagram->SetEventHandler(*this, DATAGRAM_ID);
 | |
| 		m_datagram->Notify(true);
 | |
|   }
 | |
| */
 | |
| 	
 | |
|   return m_bRunning;
 | |
| }
 | |
| 
 | |
| int TBaseServerApp::OnExit()
 | |
| {
 | |
| 	if (m_server != NULL)
 | |
| 	{
 | |
|     m_bRunning = false;
 | |
|     Deinitialization();
 | |
| 		delete m_SingleInstance;
 | |
|     m_SingleInstance = NULL;
 | |
|   	delete m_server;
 | |
|     m_server = NULL;
 | |
| 	}
 | |
| 	if (m_log != NULL)
 | |
| 	{
 | |
| 		wxString str;
 | |
| 		str << GetAppName() << " shutting down.";
 | |
| 		WriteLog(str);
 | |
| 	  delete m_log;
 | |
|     m_log = NULL;
 | |
| 	}
 | |
| 
 | |
| #ifdef wxHAS_TASK_BAR_ICON
 | |
|   if (m_Tray != NULL) 
 | |
|   {
 | |
|     m_Tray->RemoveIcon();
 | |
|     delete m_Tray;
 | |
|     m_Tray = NULL;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
| 	return wxApp::OnExit();
 | |
| }
 | |
| 
 | |
| wxString TBaseServerApp::UnformatString(const wxString& strFormString) const
 | |
| {
 | |
| 	wxString strResult;
 | |
| 	for (int i = 0; strFormString[i]; i++)
 | |
| 	{
 | |
| 		switch(strFormString[i])
 | |
| 		{
 | |
| 		case '+': 
 | |
| 			strResult += ' '; break;
 | |
| 		case '%':
 | |
| 			{
 | |
| 				const wxChar c = hex2int(strFormString.Mid(i+1, 2));
 | |
| 				strResult += c;
 | |
| 				i += 2;
 | |
| 			}
 | |
| 			break;
 | |
| 		default: 
 | |
| 			strResult += strFormString[i]; break;
 | |
| 		}
 | |
| 	}
 | |
| 	return strResult;
 | |
| }
 | |
| 
 | |
| size_t TBaseServerApp::ParseArguments(wxString args, THashTable& hashArgs) const
 | |
| {
 | |
|   int uguale = args.Find('=');
 | |
| 	while (uguale > 0)
 | |
| 	{
 | |
| 		wxString name = args.Left(uguale); 
 | |
| 		name.Trim(false); name.Trim(true);
 | |
| 		
 | |
| 		wxString value;
 | |
| 		const int acapo = args.Find('&');
 | |
| 		if (acapo > uguale)
 | |
| 	    value = args.Mid(uguale+1, acapo-uguale-1); 
 | |
| 		else
 | |
| 			value = args.Mid(uguale+1); 
 | |
| 		value.Trim(false); value.Trim(true);
 | |
| 		hashArgs.Put(name, UnformatString(value));
 | |
| 
 | |
| 		if (acapo > 0)
 | |
| 		{
 | |
|       args = args.Mid(acapo+1);
 | |
| 			uguale = args.Find('=');
 | |
| 		}
 | |
| 		else
 | |
| 			uguale = -1;
 | |
| 	}
 | |
| 	return hashArgs.GetCount();
 | |
| }	
 | |
| 
 | |
| bool TBaseServerApp::GetVersionInfo(int& year, int& release, int& tag, int& patch) const
 | |
| {                             
 | |
|   const char* const VERSIONANDPATCH = "Don't cry for me Argentina.2091.10.00.0000.2101";
 | |
|   wxStringTokenizer tok(VERSIONANDPATCH, wxT("."));
 | |
| 
 | |
|   tok.GetNextToken();             // Ignore string
 | |
|   year         = wxAtoi(tok.GetNextToken());
 | |
|   release      = wxAtoi(tok.GetNextToken());
 | |
|   tag          = wxAtoi(tok.GetNextToken());
 | |
|   patch        = wxAtoi(tok.GetNextToken());
 | |
|   int checksum = wxAtoi(tok.GetNextToken());
 | |
| 
 | |
|   bool valid = year >= 2091 && release > 0 && tag >= 0 && patch >= 0 && 
 | |
|                checksum == (year + release + tag + patch);
 | |
|   return valid;             
 | |
| }
 |