Пример #1
0
void plugin_server::load_service_config(const std::string& config_name)
{
    std::string config_file;
    if (! plugin::find_config_file(config_file, config_name))
        BOOST_THROW_EXCEPTION( error::file_not_found() << error::errinfo_file_name(config_name) );
    
    // open the file for reading
    std::ifstream config_stream;
    config_stream.open(config_file.c_str(), std::ios::in);
    if (! config_stream.is_open())
        BOOST_THROW_EXCEPTION( error::open_file() << error::errinfo_file_name(config_name) );
    
    // parse the contents of the file
    http::auth_ptr my_auth_ptr;
    enum ParseState {
        PARSE_NEWLINE, PARSE_COMMAND, PARSE_RESOURCE, PARSE_VALUE, PARSE_COMMENT, PARSE_USERNAME
    } parse_state = PARSE_NEWLINE;
    std::string command_string;
    std::string resource_string;
    std::string username_string;
    std::string value_string;
    std::string option_name_string;
    std::string option_value_string;
    int c = config_stream.get();    // read the first character
    
    while (config_stream) {
        switch(parse_state) {
        case PARSE_NEWLINE:
            // parsing command portion (or beginning of line)
            if (c == '#') {
                // line is a comment
                parse_state = PARSE_COMMENT;
            } else if (isalpha(c)) {
                // first char in command
                parse_state = PARSE_COMMAND;
                // ignore case for commands
                command_string += tolower(c);
            } else if (c != '\r' && c != '\n') {    // check for blank lines
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
            }
            break;
            
        case PARSE_COMMAND:
            // parsing command portion (or beginning of line)
            if (c == ' ' || c == '\t') {
                // command finished -> check if valid
                if (command_string=="path" || command_string=="auth" || command_string=="restrict") {
                    value_string.clear();
                    parse_state = PARSE_VALUE;
                } else if (command_string=="service" || command_string=="option") {
                    resource_string.clear();
                    parse_state = PARSE_RESOURCE;
                } else if (command_string=="user") {
                    username_string.clear();
                    parse_state = PARSE_USERNAME;
                } else {
                    BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                }
            } else if (! isalpha(c)) {
                // commands may only contain alpha chars
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
            } else {
                // ignore case for commands
                command_string += tolower(c);
            }
            break;

        case PARSE_RESOURCE:
            // parsing resource portion (/hello)
            if (c == ' ' || c == '\t') {
                // check for leading whitespace
                if (! resource_string.empty()) {
                    // resource finished
                    value_string.clear();
                    parse_state = PARSE_VALUE;
                }
            } else if (c == '\r' || c == '\n') {
                // line truncated before value
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
            } else {
                // add char to resource
                resource_string += c;
            }
            break;
        
        case PARSE_USERNAME:
            // parsing username for user command
            if (c == ' ' || c == '\t') {
                // check for leading whitespace
                if (! username_string.empty()) {
                    // username finished
                    value_string.clear();
                    parse_state = PARSE_VALUE;
                }
            } else if (c == '\r' || c == '\n') {
                // line truncated before value (missing username)
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
            } else {
                // add char to username
                username_string += c;
            }
            break;
        
        case PARSE_VALUE:
            // parsing value portion
            if (c == '\r' || c == '\n') {
                // value is finished
                if (value_string.empty()) {
                    // value must not be empty
                    BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                } else if (command_string == "path") {
                    // finished path command
                    try { plugin::add_plugin_directory(value_string); }
                    catch (std::exception& e) {
                        PION_LOG_WARN(m_logger, boost::diagnostic_information(e));
                    }
                } else if (command_string == "auth") {
                    // finished auth command
                    user_manager_ptr user_mgr(new user_manager);
                    if (value_string == "basic"){
                        my_auth_ptr.reset(new http::basic_auth(user_mgr));
                    }
                    else if (value_string == "cookie"){
                        my_auth_ptr.reset(new http::cookie_auth(user_mgr));
                    }
                    else {
                        // only basic and cookie authentications are supported
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                    }
                } else if (command_string == "restrict") {
                    // finished restrict command
                    if (! my_auth_ptr)
                        // Authentication type must be defined before restrict
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                    else if (value_string.empty())
                        // No service defined for restrict parameter
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                    my_auth_ptr->add_restrict(value_string);
                } else if (command_string == "user") {
                    // finished user command
                    if (! my_auth_ptr)
                        // Authentication type must be defined before users
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                    else if (value_string.empty())
                        // No password defined for user parameter
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                    my_auth_ptr->add_user(username_string, value_string);
                } else if (command_string == "service") {
                    // finished service command
                    load_service(resource_string, value_string);
                } else if (command_string == "option") {
                    // finished option command
                    std::string::size_type pos = value_string.find('=');
                    if (pos == std::string::npos)
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
                    option_name_string = value_string.substr(0, pos);
                    option_value_string = value_string.substr(pos + 1);
                    set_service_option(resource_string, option_name_string,
                                     option_value_string);
                }
                command_string.clear();
                parse_state = PARSE_NEWLINE;
            } else if (c == ' ' || c == '\t') {
                // only skip leading whitespace (value may contain spaces, etc)
                if (! value_string.empty())
                    value_string += c;
            } else {
                // add char to value
                value_string += c;
            }
            break;
        
        case PARSE_COMMENT:
            // skipping comment line
            if (c == '\r' || c == '\n')
                parse_state = PARSE_NEWLINE;
            break;
        }

        // read the next character
        c = config_stream.get();
    }
    
    // update authentication configuration for the server
    set_authentication(my_auth_ptr);
}
Пример #2
0
void HTTPServer::handleRequest(HTTPRequestPtr& http_request,
							   TCPConnectionPtr& tcp_conn)
{
	if (! http_request->isValid()) {
		// the request is invalid or an error occured
		PION_LOG_INFO(m_logger, "Received an invalid HTTP request");
		m_bad_request_handler(http_request, tcp_conn);
		return;
	}
		
	PION_LOG_DEBUG(m_logger, "Received a valid HTTP request");

	// strip off trailing slash if the request has one
	std::string resource_requested(stripTrailingSlash(http_request->getResource()));

	// apply any redirection
	RedirectMap::const_iterator it = m_redirects.find(resource_requested);
	unsigned int num_redirects = 0;
	while (it != m_redirects.end()) {
		if (++num_redirects > MAX_REDIRECTS) {
			PION_LOG_ERROR(m_logger, "Maximum number of redirects (HTTPServer::MAX_REDIRECTS) exceeded for requested resource: " << http_request->getOriginalResource());
			m_server_error_handler(http_request, tcp_conn, "Maximum number of redirects (HTTPServer::MAX_REDIRECTS) exceeded for requested resource");
			return;
		}
		resource_requested = it->second;
		http_request->changeResource(resource_requested);
		it = m_redirects.find(resource_requested);
	}

	// if authentication activated, check current request
	if (m_auth) {
		// try to verify authentication
		if (! m_auth->handleRequest(http_request, tcp_conn)) {
			// the HTTP 401 message has already been sent by the authentication object
			PION_LOG_DEBUG(m_logger, "Authentication required for HTTP resource: "
				<< resource_requested);
			if (http_request->getResource() != http_request->getOriginalResource()) {
				PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource());
			}
			return;
		}
	}
	
	// search for a handler matching the resource requested
	RequestHandler request_handler;
	if (findRequestHandler(resource_requested, request_handler)) {
		
		// try to handle the request
		try {
			request_handler(http_request, tcp_conn);
			PION_LOG_DEBUG(m_logger, "Found request handler for HTTP resource: "
						   << resource_requested);
			if (http_request->getResource() != http_request->getOriginalResource()) {
				PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource());
			}
		} catch (HTTPResponseWriter::LostConnectionException& e) {
			// the connection was lost while or before sending the response
			PION_LOG_WARN(m_logger, "HTTP request handler: " << e.what());
			tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);	// make sure it will get closed
			tcp_conn->finish();
		} catch (std::bad_alloc&) {
			// propagate memory errors (FATAL)
			throw;
		} catch (std::exception& e) {
			// recover gracefully from other exceptions thrown request handlers
			PION_LOG_ERROR(m_logger, "HTTP request handler: " << e.what());
			m_server_error_handler(http_request, tcp_conn, e.what());
		}
		
	} else {
		
		// no web services found that could handle the request
		PION_LOG_INFO(m_logger, "No HTTP request handlers found for resource: "
					  << resource_requested);
		if (http_request->getResource() != http_request->getOriginalResource()) {
			PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource());
		}
		m_not_found_handler(http_request, tcp_conn);
	}
}