Beispiel #1
0
void WebServer::get(BaseLib::HTTP& http, std::shared_ptr<BaseLib::SocketOperations> socket)
{
	try
	{
		if(!socket)
		{	_out.printError("Error: Socket is nullptr.");
			return;
		}
		std::string path = http.getHeader()->path;

		BaseLib::EventHandlers eventHandlers = getEventHandlers();
		for(BaseLib::EventHandlers::const_iterator i = eventHandlers.begin(); i != eventHandlers.end(); ++i)
		{
			i->second->lock();
			if(i->second->handler() && ((BaseLib::Rpc::IWebserverEventSink*)i->second->handler())->onGet(_serverInfo, http, socket, path))
			{
				i->second->unlock();
				return;
			}
			i->second->unlock();
		}

		std::vector<std::string> headers;
		std::vector<char> content;
		if(!path.empty() && path.front() == '/') path = path.substr(1);

		bool isDirectory = false;
		BaseLib::Io::isDirectory(_serverInfo->contentPath + path, isDirectory);
		if(isDirectory)
		{
			if(!path.empty() && path.back() != '/')
			{
				path.push_back('/');
				std::vector<std::string> additionalHeaders({std::string("Location: ") + path});
				getError(301, "Moved Permanently", "The document has moved <a href=\"" + path + "\">here</a>.", content, additionalHeaders);
				send(socket, content);
				return;
			}
			if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.php")) path += "index.php";
			else if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.php5")) path += "index.php5";
			else if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.php7")) path += "index.php7";
			else if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.html")) path += "index.html";
			else if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.htm")) path += "index.htm";
			else
			{
				getError(404, "Not Found", "The requested URL / was not found on this server.", content);
				send(socket, content);
				return;
			}
		}

		if(!BaseLib::Io::fileExists(_serverInfo->contentPath + path))
		{
			getError(404, _http.getStatusText(404), "The requested URL " + path + " was not found on this server.", content);
			send(socket, content);
			return;
		}

		try
		{
			_out.printInfo("Client is requesting: " + http.getHeader()->path + " (translated to " + _serverInfo->contentPath + path + ", method: GET)");
			std::string ending = "";
			int32_t pos = path.find_last_of('.');
			if(pos != (signed)std::string::npos && (unsigned)pos < path.size() - 1) ending = path.substr(pos + 1);
			GD::bl->hf.toLower(ending);
			std::string contentString;
#ifdef SCRIPTENGINE
			if(ending == "php" || ending == "php5" || ending == "php7")
			{
				GD::scriptEngine->executeWebRequest(_serverInfo->contentPath + path, http, _serverInfo, socket);
				socket->close();
				return;
			}
#endif
			std::string contentType = _http.getMimeType(ending);
			if(contentType.empty()) contentType = "application/octet-stream";
			//Don't return content when method is "HEAD"
			if(http.getHeader()->method == "GET") contentString = GD::bl->io.getFileContent(_serverInfo->contentPath + path);
			std::string header;
			_http.constructHeader(contentString.size(), contentType, 200, "OK", headers, header);
			content.insert(content.end(), header.begin(), header.end());
			if(!contentString.empty()) content.insert(content.end(), contentString.begin(), contentString.end());
			send(socket, content);
		}
		catch(const std::exception& ex)
		{
			getError(404, _http.getStatusText(404), "The requested URL " + path + " was not found on this server.", content);
			send(socket, content);
			return;
		}
		catch(BaseLib::Exception& ex)
		{
			getError(404, _http.getStatusText(404), "The requested URL " + path + " was not found on this server.", content);
			send(socket, content);
			return;
		}
	}
	catch(const std::exception& ex)
    {
    	_out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
    }
    catch(BaseLib::Exception& ex)
    {
    	_out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
    }
    catch(...)
    {
    	_out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
    }
}
Beispiel #2
0
bool Auth::basicServer(BaseLib::HTTP& httpPacket)
{
	if(!_initialized) throw AuthException("Not initialized.");
	_http.reset();
	uint32_t bufferLength = 1024;
	char buffer[bufferLength + 1];
	if(httpPacket.getHeader()->authorization.empty())
	{
		if(_basicAuthHTTPHeader.empty())
		{
			_basicAuthHTTPHeader.append("HTTP/1.1 401 Authorization Required\r\n");
			_basicAuthHTTPHeader.append("WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n");
			_basicAuthHTTPHeader.append("Connection: Keep-Alive\r\n");
			std::string content("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"><title>Authorization Required</title></head><body>Authorization Required</body></html>");
			_basicAuthHTTPHeader.append("Content-Length: " + std::to_string(content.size()) + "\r\n\r\n");
			_basicAuthHTTPHeader.append(content);
		}
		std::shared_ptr<std::vector<char>> data(new std::vector<char>());
		data->insert(data->begin(), _basicAuthHTTPHeader.begin(), _basicAuthHTTPHeader.end());
		try
		{
			_socket->proofwrite(data);
			int32_t bytesRead = _socket->proofread(buffer, bufferLength);
			//Some clients send only one byte in the first packet
			if(bytesRead == 1) bytesRead += _socket->proofread(&buffer[1], bufferLength - 1);
			buffer[bytesRead] = '\0';
			try
			{
				_http.process(buffer, bufferLength);
			}
			catch(BaseLib::HTTPException& ex)
			{
				throw AuthException("Authorization failed because of HTTP exception: " + ex.what());
			}
		}
		catch(const BaseLib::SocketOperationException& ex)
		{
			throw AuthException("Authorization failed because of socket exception: " + ex.what());
		}
	}
	else _http = httpPacket;
	if(_http.getHeader()->authorization.empty())
	{
		sendBasicUnauthorized(false);
		throw AuthException("No header field \"Authorization\"");
	}
	std::pair<std::string, std::string> authData = BaseLib::HelperFunctions::splitLast(_http.getHeader()->authorization, ' ');
	BaseLib::HelperFunctions::toLower(authData.first);
	if(authData.first != "basic")
	{
		sendBasicUnauthorized(false);
		throw AuthException("Authorization type is not basic but: " + authData.first);
	}
	std::string decodedData;
	BaseLib::Base64::decode(authData.second, decodedData);
	std::pair<std::string, std::string> credentials = BaseLib::HelperFunctions::splitLast(decodedData, ':');
	BaseLib::HelperFunctions::toLower(credentials.first);
	if(std::find(_validUsers.begin(), _validUsers.end(), credentials.first) == _validUsers.end())
	{
		sendBasicUnauthorized(false);
		throw AuthException("User name " + credentials.first + " is not in the list of valid users in /etc/homegear/rpcservers.conf.");
	}
	if(User::verify(credentials.first, credentials.second)) return true;
	sendBasicUnauthorized(false);
	return false;
}
Beispiel #3
0
void WebServer::post(BaseLib::HTTP& http, std::shared_ptr<BaseLib::SocketOperations> socket)
{
	try
	{
		std::vector<char> content;
#ifdef SCRIPTENGINE
		if(!socket)
		{	_out.printError("Error: Socket is nullptr.");
			return;
		}
		std::string path = http.getHeader()->path;

		BaseLib::EventHandlers eventHandlers = getEventHandlers();
		for(BaseLib::EventHandlers::const_iterator i = eventHandlers.begin(); i != eventHandlers.end(); ++i)
		{
			i->second->lock();
			if(i->second->handler() && ((BaseLib::Rpc::IWebserverEventSink*)i->second->handler())->onGet(_serverInfo, http, socket, path))
			{
				i->second->unlock();
				return;
			}
			i->second->unlock();
		}

		if(!path.empty() && path.front() == '/') path = path.substr(1);

		bool isDirectory = false;
		BaseLib::Io::isDirectory(_serverInfo->contentPath + path, isDirectory);
		if(isDirectory)
		{
			if(!path.empty() && path.back() != '/')
			{
				path.push_back('/');
				std::vector<std::string> additionalHeaders({std::string("Location: ") + path});
				getError(301, "Moved Permanently", "The document has moved <a href=\"" + path + "\">here</a>.", content, additionalHeaders);
				send(socket, content);
				return;
			}
			if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.php")) path += "index.php";
			else if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.php5")) path += "index.php5";
			else if(GD::bl->io.fileExists(_serverInfo->contentPath + path + "index.php7")) path += "index.php7";
			else
			{
				getError(404, _http.getStatusText(404), "The requested URL / was not found on this server.", content);
				send(socket, content);
				return;
			}
		}

		if(!BaseLib::Io::fileExists(_serverInfo->contentPath + path))
		{
			getError(404, _http.getStatusText(404), "The requested URL " + path + " was not found on this server.", content);
			send(socket, content);
			return;
		}

		try
		{
			_out.printInfo("Client is requesting: " + http.getHeader()->path + " (translated to: \"" + _serverInfo->contentPath + path + "\", method: POST)");
			GD::scriptEngine->executeWebRequest(_serverInfo->contentPath + path, http, _serverInfo, socket);
			socket->close();
		}
		catch(const std::exception& ex)
		{
			getError(404, _http.getStatusText(404), "The requested URL " + path + " was not found on this server.", content);
			send(socket, content);
			return;
		}
		catch(BaseLib::Exception& ex)
		{
			getError(404, _http.getStatusText(404), "The requested URL " + path + " was not found on this server.", content);
			send(socket, content);
			return;
		}
#else
		getError(304, _http.getStatusText(304), "Homegear is compiled without script engine.", content);
		send(socket, content);
#endif
	}
	catch(const std::exception& ex)
    {
    	_out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
    }
    catch(BaseLib::Exception& ex)
    {
    	_out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
    }
    catch(...)
    {
    	_out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
    }
}
Beispiel #4
0
int32_t ScriptEngine::executeWebRequest(const std::string& path, BaseLib::HTTP& request, std::shared_ptr<BaseLib::Rpc::ServerInfo::Info>& serverInfo, std::shared_ptr<BaseLib::SocketOperations>& socket)
{
	if(_disposing) return 1;
	if(!GD::bl->io.fileExists(path))
	{
		GD::out.printError("Error: PHP script \"" + path + "\" does not exist.");
		return -1;
	}
	ts_resource_ex(0, NULL); //Replaces TSRMLS_FETCH()
	try
	{
		zend_file_handle script;

		script.type = ZEND_HANDLE_FILENAME;
		script.filename = path.c_str();
		script.opened_path = NULL;
		script.free_filename = 0;

		zend_homegear_globals* globals = php_homegear_get_globals();
		if(!globals)
		{
			ts_free_thread();
			return -1;
		}
		globals->socket = socket.get();
		globals->http = &request;

		if(!tsrm_get_ls_cache())
		{
			GD::out.printCritical("Critical: Error in PHP: No thread safe resource exists (1).");
			ts_free_thread();
			return -1;
		}
		if(!((sapi_globals_struct *) (*((void ***) tsrm_get_ls_cache()))[((sapi_globals_id)-1)]))
		{
			GD::out.printCritical("Critical: Error in PHP: No thread safe resource exists (2).");
			ts_free_thread();
			return -1;
		}
		SG(server_context) = (void*)serverInfo.get(); //Must be defined! Otherwise POST data is not processed.
		SG(sapi_headers).http_response_code = 200;
		SG(default_mimetype) = nullptr;
		SG(default_charset) = nullptr;
		SG(request_info).content_length = request.getHeader()->contentLength;
		if(!request.getHeader()->contentType.empty()) SG(request_info).content_type = request.getHeader()->contentType.c_str();
		SG(request_info).request_method = request.getHeader()->method.c_str();
		SG(request_info).proto_num = request.getHeader()->protocol == BaseLib::HTTP::Protocol::http10 ? 1000 : 1001;
		std::string uri = request.getHeader()->path + request.getHeader()->pathInfo;
		if(!request.getHeader()->args.empty()) uri.append('?' + request.getHeader()->args);
		if(!request.getHeader()->args.empty()) SG(request_info).query_string = estrndup(&request.getHeader()->args.at(0), request.getHeader()->args.size());
		if(!uri.empty()) SG(request_info).request_uri = estrndup(&uri.at(0), uri.size());
		std::string pathTranslated = serverInfo->contentPath.substr(0, serverInfo->contentPath.size() - 1) + request.getHeader()->pathInfo;
		SG(request_info).path_translated = estrndup(&pathTranslated.at(0), pathTranslated.size());

		if (php_request_startup() == FAILURE) {
			GD::bl->out.printError("Error calling php_request_startup...");
			ts_free_thread();
			return 1;
		}

		php_execute_script(&script);

		int32_t exitCode = EG(exit_status);

		if(SG(request_info).query_string)
		{
			efree(SG(request_info).query_string);
			SG(request_info).query_string = nullptr;
		}
		if(SG(request_info).request_uri)
		{
			efree(SG(request_info).request_uri);
			SG(request_info).request_uri = nullptr;
		}
		if(SG(request_info).path_translated)
		{
			efree(SG(request_info).path_translated);
			SG(request_info).path_translated = nullptr;
		}

		php_request_shutdown(NULL);

		ts_free_thread();
		return exitCode;
	}
	catch(const std::exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(BaseLib::Exception& ex)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
	}
	catch(...)
	{
		GD::bl->out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
	}
	std::string error("Error executing script. Check Homegear log for more details.");
	if(socket) php_homegear_write_socket(socket.get(), error.c_str(), error.length());
	if(SG(request_info).query_string)
	{
		efree(SG(request_info).query_string);
		SG(request_info).query_string = nullptr;
	}
	if(SG(request_info).request_uri)
	{
		efree(SG(request_info).request_uri);
		SG(request_info).request_uri = nullptr;
	}
	if(SG(request_info).path_translated)
	{
		efree(SG(request_info).path_translated);
		SG(request_info).path_translated = nullptr;
	}
	ts_free_thread();
	return 1;
}