Files correlati : Ricompilazione Demo : [ ] Commento :correzioni al server git-svn-id: svn://10.65.10.50/trunk@16094 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			438 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			438 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include "baseserv.h"
 | |
| 
 | |
| #include <wx/config.h>
 | |
| #ifdef WIN32
 | |
| #include <wx/fileconf.h>
 | |
| #endif
 | |
| 
 | |
| #include <ctype.h>
 | |
| 
 | |
| class TLurchServer : public TBaseServerApp
 | |
| {
 | |
| protected:  
 | |
| 	virtual const wxChar* GetAppName() const;
 | |
|   virtual bool Initialization();
 | |
| 
 | |
| 	void AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const;
 | |
|   void EnumerateVariables(const wxString& strApp, wxArrayString& arr) const;
 | |
| 
 | |
|   void CreateServersList(wxArrayString& arr) const;
 | |
|   void KillProcess(const wxString& strApp);
 | |
| 
 | |
| public:
 | |
| 	void GenerateFile(wxString& strFilename);
 | |
|   bool IsMagicName(wxString& strFilename) const;
 | |
|   bool IsCgiName(wxString strFilename) const;
 | |
| 
 | |
|   void ProcessHttpGet(wxString cmd, wxSocketBase& outs);
 | |
|   void ProcessHttpPost(wxString cmd, wxSocketBase& outs);
 | |
| 
 | |
| 	void ProcessFormStart(const THashTable& args, wxSocketBase& sock);
 | |
|   void ProcessFormKill(const THashTable& args, wxSocketBase& sock);
 | |
|   void ProcessFormConfig(const THashTable& args, wxSocketBase& sock);
 | |
|   void ProcessFormUpdate(THashTable& args, wxSocketBase& sock);
 | |
|   void CallCgi(wxString& strFileName, wxSocketBase& sock);
 | |
| };
 | |
| 
 | |
| const wxChar* TLurchServer::GetAppName() const
 | |
| {
 | |
| 	return "Lurch";
 | |
| }
 | |
| 
 | |
| void TLurchServer::CreateServersList(wxArrayString& arr) const
 | |
| {
 | |
| 	wxFileInputStream ini(GetConfigName());
 | |
|   const size_t size = ini.GetSize();
 | |
| 	wxChar* buff = new wxChar[size];
 | |
| 	ini.Read(buff, size);
 | |
| 
 | |
| 	const char* aperta = strchr(buff, '[');
 | |
| 	while (aperta != NULL)
 | |
| 	{
 | |
|     char* chiusa = (char*)strchr(aperta+1, ']');
 | |
| 		if (chiusa != NULL)
 | |
| 		{
 | |
| 			*chiusa = '\0';
 | |
| 			wxString str = aperta+1;
 | |
| 		  arr.Add(str);
 | |
| 			aperta = strchr(chiusa+1, '[');
 | |
| 		}
 | |
| 		else
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	delete buff;
 | |
| }
 | |
| 
 | |
| void TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const
 | |
| {
 | |
| 	TXmlItem& td = tr.AddChild("td").SetAttr("width", "15%");
 | |
|   TXmlItem& form = td.AddChild("center").AddChild("form");
 | |
| 	form.SetAttr("action", action);
 | |
| 	
 | |
| 	TXmlItem& name = form.AddChild("input");
 | |
| 	name.SetAttr("type", "hidden"); name.SetAttr("name", "App");
 | |
| 	name.SetAttr("value", app);
 | |
| 
 | |
| 	TXmlItem& submit = form.AddChild("input");
 | |
| 	submit.SetAttr("type", "submit"); 
 | |
| 	submit.SetAttr("value", prompt); 
 | |
| }
 | |
| 
 | |
| void TLurchServer::GenerateFile(wxString& strFilename)
 | |
| {
 | |
| 	TXmlItem html; 
 | |
| 	TXmlItem& body = CreatePageBody(html);
 | |
| 
 | |
| 	if (strFilename == "index")
 | |
| 	{
 | |
| 		TXmlItem& table = body.AddChild("table");
 | |
| 		table.SetAttr("border", "1"); table.SetAttr("width", "100%");
 | |
| 		strFilename = GetTempFilename();
 | |
| 		const wxString strLurchName = GetAppName();
 | |
| 
 | |
|     wxArrayString arr; CreateServersList(arr);
 | |
| 		for (size_t i = 0; i < arr.GetCount(); i++)
 | |
| 		{
 | |
| 			const bool bLurch = arr[i] == strLurchName;
 | |
| 			wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
 | |
| 			wxString str;
 | |
| 			str << '/' << arr[i];
 | |
| 			ini.SetPath(str);
 | |
| 
 | |
|       wxString strHost; 
 | |
| 			ini.Read("Host", &strHost, wxGetFullHostName());
 | |
| 
 | |
| 			int nPort;
 | |
| 			ini.Read("Port", &nPort, 3883);
 | |
| 
 | |
|       wxString strIcon; 
 | |
| 			ini.Read("Icon", &strIcon, "euro.gif");
 | |
| 
 | |
| 			const wxSingleInstanceChecker sic(arr[i]);
 | |
| 			const bool bRunning = sic.IsAnotherRunning();
 | |
| 
 | |
| 			TXmlItem& tr = table.AddChild("tr");
 | |
| 			TXmlItem& td0 = tr.AddChild("td");
 | |
| 			td0.SetAttr("width", "15%"); td0.SetAttr("align", "center");
 | |
| 			TXmlItem& a = td0.AddChild("a");
 | |
| 			if (!bLurch && bRunning)
 | |
| 			{
 | |
| 				a.SetAttr("href", wxString::Format("http://%s:%d/index.htm", strHost.c_str(), nPort));
 | |
| 				a.SetAttr("target", "_blank");
 | |
| 			} 
 | |
|  			TXmlItem& img = a.AddChild("img");
 | |
| 			img.SetAttr("src", strIcon); img.SetAttr("border", 0L); img.SetAttr("alt", arr[i]);
 | |
| 
 | |
| 			AddMiniForm(tr, (bRunning || bLurch) ? "kill.cgi" : "start.cgi", arr[i], (bRunning || bLurch) ? "Stop" : "Start");
 | |
| 			AddMiniForm(tr, "config.cgi", arr[i], "Configure");
 | |
| 
 | |
| 			TXmlItem& a3 = tr.AddChild("td").AddChild("a");
 | |
| 			if (!bLurch && bRunning)
 | |
| 			{
 | |
| 				a3.SetAttr("href", wxString::Format("http://%s:%d/index.htm", strHost.c_str(), nPort)); 
 | |
| 				a3.SetAttr("target", "_blank"); 
 | |
|       }
 | |
|      	a3 << arr[i] << " Server";
 | |
| 		}
 | |
| 
 | |
| 		html.Save(strFilename);
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool TLurchServer::IsMagicName(wxString& strFilename) const
 | |
| {
 | |
|   wxString strName;
 | |
| 	wxSplitPath(strFilename, NULL, &strName, NULL);
 | |
|   strName.MakeLower();
 | |
| 	if (strName == "index")
 | |
| 	{
 | |
| 		strFilename = strName;
 | |
| 		return true;
 | |
| 	}
 | |
| 	if (strName == "log")
 | |
| 	{
 | |
| 		strFilename = GetLogFileName();
 | |
| 	}
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool TLurchServer::IsCgiName(wxString strFilename) const
 | |
| {
 | |
| 	const int q = strFilename.Find('?');
 | |
| 	if (q > 0)
 | |
| 		strFilename.Truncate(q);
 | |
| 
 | |
| 	wxString strExt;
 | |
| 	wxSplitPath(strFilename, NULL, NULL, &strExt);
 | |
|   strExt.MakeLower();
 | |
| 	return strExt == "cgi" || strExt == "exe";
 | |
| }
 | |
| 
 | |
| void TLurchServer::ProcessFormStart(const THashTable& args, wxSocketBase& sock)
 | |
| {
 | |
| 	bool ok = false;
 | |
| 
 | |
|   const wxString strApp = args.Get("App");
 | |
| 	if (!strApp.IsEmpty()) // Dummy test
 | |
| 	{
 | |
|   	const wxSingleInstanceChecker sic(strApp);
 | |
| 		ok = !sic.IsAnotherRunning();
 | |
| 	}
 | |
| 	
 | |
| 	if (ok)
 | |
| 	{
 | |
| 		wxString strRun = GetConfigString("Run", "", strApp);
 | |
| 		if (wxFileExists(strRun))
 | |
| 		{
 | |
| #ifdef LINUX
 | |
| 			if (strRun[ 0u] != '/' && strRun[ 0u] != '.')
 | |
| 				strRun = "./" + strRun;
 | |
| #endif
 | |
| 			const long nProc = wxExecute(strRun);
 | |
| 			if (nProc == 0 || nProc == -1)
 | |
| 				MessageBox("ERROR", wxString::Format("Can't run %s executable (%s)", strApp.c_str(), 
 | |
| 				                                     strRun.c_str()), sock);
 | |
| 			else
 | |
| 			  MessageBox("Server Started", strApp, sock);
 | |
| 		}
 | |
| 		else
 | |
| 			MessageBox("ERROR", wxString::Format("Can't find %s executable (%s)", strApp.c_str(),
 | |
| 			                                     strRun.c_str()), sock);
 | |
| 	}
 | |
| 	else
 | |
| 		MessageBox("ERROR", wxString::Format("%s il already running", strApp.c_str()), sock);
 | |
| }
 | |
| 
 | |
| void TLurchServer::KillProcess(const wxString& strApp)
 | |
| {
 | |
| 	const wxString strHost = GetConfigString("Host", "localhost", strApp);
 | |
| 	const int nPort = GetConfigInt("Port", 0, strApp);
 | |
| 	if (nPort > 0)
 | |
| 	{
 | |
| 		wxIPV4address addr;
 | |
| 		addr.Hostname(strHost);
 | |
| 		addr.Service(nPort);
 | |
| 
 | |
| 		wxSocketClient sock;
 | |
| 		if (sock.Connect(addr))
 | |
| 		{
 | |
|   		const wxString str = "GET /stop.cgi HTTP/1.1\r\n\r\n";
 | |
| 			sock.Write(str, str.Length());
 | |
| 			if (strHost == "localhost")
 | |
| 			{
 | |
| 				const wxSingleInstanceChecker sic(strApp);
 | |
| 				for (int i = 0; i < 5 && sic.IsAnotherRunning(); i++)
 | |
| 					wxSleep(1);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void TLurchServer::ProcessFormKill(const THashTable& args, wxSocketBase& sock)
 | |
| {
 | |
|   const wxString strApp = args.Get("App");
 | |
| 	if (strApp == GetAppName()) // Stop myself!
 | |
| 	{
 | |
| 	  wxArrayString app; CreateServersList(app);
 | |
|     for (size_t i = 0; i < app.GetCount(); i++)
 | |
| 		{
 | |
| 			if (app[i] != GetAppName())  // Stop Children only!
 | |
| 			{
 | |
|   			const wxSingleInstanceChecker sic(app[i]);
 | |
| 				if (sic.IsAnotherRunning())
 | |
| 	        KillProcess(app[i]);		
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	KillProcess(strApp);
 | |
|   MessageBox("Server stopped", strApp, sock);
 | |
| }
 | |
| 
 | |
| void TLurchServer::EnumerateVariables(const wxString& strApp, wxArrayString& arr) const
 | |
| {
 | |
| 	wxFileInputStream inf(GetConfigName());
 | |
| 	wxString strParagraph = wxString::Format("[%s]", strApp.c_str());
 | |
| 	wxString str;
 | |
| 
 | |
| 	bool bFound = false;
 | |
| 	while (inf.Ok())
 | |
| 	{
 | |
|     inf >> str;
 | |
|     if (str == strParagraph)
 | |
| 		{
 | |
| 			bFound = true;
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (bFound)
 | |
| 	{
 | |
| 		while (inf.Ok())
 | |
| 		{
 | |
| 			inf >> str;
 | |
| 			if (str.IsEmpty() || str[0u] == '[')
 | |
| 				break;
 | |
| 			const int nEqual = str.Find('=');
 | |
|       if (nEqual > 0)
 | |
| 			{
 | |
| 				str.Truncate(nEqual);
 | |
| 				str.Trim(false);
 | |
| 				str.Trim(true);
 | |
| 				arr.Add(str);
 | |
| 			}
 | |
| 		}
 | |
| 		arr.Sort();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void TLurchServer::ProcessFormConfig(const THashTable& args, wxSocketBase& sock)
 | |
| {
 | |
|   const wxString strApp = args.Get("App");
 | |
|   wxArrayString arr;
 | |
| 	EnumerateVariables(strApp, arr);
 | |
| 
 | |
| 	TXmlItem html; 
 | |
| 	TXmlItem& body = CreatePageBody(html);
 | |
| 
 | |
|   TXmlItem& form = body.AddChild("form");
 | |
|   form.SetAttr("action", "update.cgi").SetAttr("method", "post");
 | |
| 	
 | |
| 	TXmlItem& table = form.AddChild("table").SetAttr("width", "100%").SetAttr("border", "1");
 | |
| 	table.AddChild("caption").AddChild("h2") << strApp;
 | |
| 	TXmlItem& thead = table.AddChild("thead");
 | |
| 	thead.AddChild("th").SetAttr("width", "15%") << "Property";
 | |
| 	thead.AddChild("th").SetAttr("width", "85%") << "Value";
 | |
| 
 | |
| 	for (size_t v = 0; v < arr.GetCount(); v++)
 | |
| 	{
 | |
| 		TXmlItem& tr = table.AddChild("tr");
 | |
| 		tr.AddChild("td") << arr[v];
 | |
| 		TXmlItem& input = tr.AddChild("td").AddChild("input");
 | |
| 		input.SetAttr("type", "text"); input.SetAttr("name", arr[v]);
 | |
| 		input.SetAttr("size", "80"); input.SetAttr("maxlength", "256");
 | |
| 		input.SetAttr("value", GetConfigString(arr[v], "", strApp));
 | |
| 	}
 | |
| 
 | |
| 	TXmlItem& app = form.AddChild("input").SetAttr("type", "hidden");
 | |
| 	app.SetAttr("name", "App"); app.SetAttr("value", strApp);
 | |
| 
 | |
| 	TXmlItem& submit = form.AddChild("br").AddChild("center").AddChild("input");
 | |
| 	submit.SetAttr("type", "submit"); submit.SetAttr("value", "Update Parameters");
 | |
| 
 | |
| 	body.AddChild("br");
 | |
| 	AddLinkButton(body.AddChild("center"), "Return to main page", "/");
 | |
| 
 | |
| 	const wxString strFilename = GetTempFilename();
 | |
|   html.Save(strFilename);
 | |
|   SendFile(strFilename, sock);
 | |
| }
 | |
| 
 | |
| void TLurchServer::ProcessFormUpdate(THashTable& args, wxSocketBase& sock)
 | |
| {
 | |
|   const wxString strApp = args.Get("App");
 | |
| 	args.BeginFind();
 | |
|   for (wxHashTable::Node* pNode = args.Next(); pNode; pNode = args.Next())
 | |
| 	{
 | |
| 		const wxString strKey = pNode->GetKeyString();
 | |
| 		if (strKey != "App")
 | |
| 		{
 | |
| 		  const wxString strVal = args.Get(strKey);
 | |
| 		  SetConfigString(strKey, strVal, strApp);
 | |
| 		}
 | |
| 	}
 | |
| 	const wxString msg = wxString::Format("%s parameters updated", strApp.c_str());
 | |
|   MessageBox("Success!", msg, sock);
 | |
| }
 | |
| 
 | |
| void TLurchServer::CallCgi(wxString& strFileName, wxSocketBase& sock)
 | |
| {
 | |
| 	wxString strName, strExt, strArgs;
 | |
| 	const int q = strFileName.Find('?');
 | |
| 	if (q > 0)
 | |
| 	{
 | |
| 		strArgs = strFileName.Mid(q+1);
 | |
| 		strFileName.Truncate(q);
 | |
| 	}
 | |
| 	wxSplitPath(strFileName, NULL, &strName, &strExt);
 | |
| 
 | |
| 	THashTable hashArgs(13);
 | |
|   ParseArguments(strArgs, hashArgs);
 | |
| 
 | |
| 	if (strExt == "cgi")
 | |
| 	{
 | |
| 		if (strName == "start")
 | |
| 			ProcessFormStart(hashArgs, sock); else
 | |
| 		if (strName == "kill")
 | |
| 			ProcessFormKill(hashArgs, sock); else
 | |
| 		if (strName == "config")
 | |
| 			ProcessFormConfig(hashArgs, sock); else
 | |
| 		if (strName == "update")
 | |
| 			ProcessFormUpdate(hashArgs, sock);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void TLurchServer::ProcessHttpGet(wxString cmd, wxSocketBase& outs)
 | |
| {
 | |
|   const int stop = cmd.Find(" HTTP");
 | |
| 	wxString str = cmd.Mid(4, stop-4).Trim();
 | |
| 
 | |
| 	if (str == "/")
 | |
| 		str += "index.htm";
 | |
| 	wxString strFilename = GetDocumentRoot() + str;
 | |
| 
 | |
|  	if (IsCgiName(strFilename))
 | |
| 	  CallCgi(strFilename, outs);
 | |
| 	else
 | |
| 	{
 | |
| 	  if (IsMagicName(strFilename))
 | |
| 		  GenerateFile(strFilename);
 | |
| 	  SendFile(strFilename, outs);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void TLurchServer::ProcessHttpPost(wxString cmd, wxSocketBase& outs)
 | |
| {
 | |
|   const int stop = cmd.Find(" HTTP");
 | |
| 	wxString strFileName = cmd.Mid(5, stop-5).Trim();
 | |
| 
 | |
| 	wxString strName, args;
 | |
| 	wxSplitPath(strFileName, NULL, &strName, NULL);
 | |
| 
 | |
| 	const int pos = cmd.Find("\r\n\r\n");
 | |
| 	if (pos > 0)
 | |
| 	  args = cmd.Mid(pos+4);
 | |
| 
 | |
| 	THashTable hashArgs(17);
 | |
|   ParseArguments(args, hashArgs);
 | |
| 
 | |
| 	if (strName == "update")
 | |
| 		ProcessFormUpdate(hashArgs, outs);
 | |
| }
 | |
| 
 | |
| bool TLurchServer::Initialization()
 | |
| {
 | |
|   wxArrayString arr; CreateServersList(arr);
 | |
| 	for (size_t i = 0; i < arr.GetCount(); i++)
 | |
| 	{
 | |
| 		const wxString& strApp = arr[i];
 | |
| 		const bool bAutorun = GetConfigBool("Autorun", false, strApp);
 | |
| 		if (bAutorun)
 | |
| 		{
 | |
| 			const wxSingleInstanceChecker sic(strApp);
 | |
|       if (!sic.IsAnotherRunning())
 | |
| 			{
 | |
| 				wxString strRun = GetServerPath() + GetConfigString("Run", "", strApp);
 | |
| 				if (wxFileExists(strRun))
 | |
| 					wxExecute(strRun);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| // Istanziare l'applicazione principale
 | |
| 
 | |
| IMPLEMENT_APP(TLurchServer)
 |