- Main Page
- Classes
- Files

- File List

# src/http_plugin_server.cpp

    00001 // ---------------------------------------------------------------------
    00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
    00003 // ---------------------------------------------------------------------
    00004 // Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #include <boost/exception/diagnostic_information.hpp>
    00011 #include <pion/error.hpp>
    00012 #include <pion/http/plugin_server.hpp>
    00013 #include <pion/http/request.hpp>
    00014 #include <pion/http/request_reader.hpp>
    00015 #include <pion/http/response_writer.hpp>
    00016 #include <pion/http/basic_auth.hpp>
    00017 #include <pion/http/cookie_auth.hpp>
    00018 #include <fstream>
    00019
    00020
    00021 namespace pion {    // begin namespace pion
    00022 namespace http {    // begin namespace http
    00023
    00024
    00025 // plugin_server member functions
    00026
    00027 void plugin_server::add_service(const std::string& resource, http::plugin_service *service_ptr)
    00028 {
    00029     plugin_ptr<http::plugin_service> plugin_ptr;
    00030     const std::string clean_resource(strip_trailing_slash(resource));
    00031     service_ptr->set_resource(clean_resource);
    00032     m_services.add(clean_resource, service_ptr);
    00033     http::server::add_resource(clean_resource, boost::ref(*service_ptr));
    00034     PION_LOG_INFO(m_logger, "Loaded static web service for resource (" << clean_resource << ")");
    00035 }
    00036
    00037 void plugin_server::load_service(const std::string& resource, const std::string& service_name)
    00038 {
    00039     const std::string clean_resource(strip_trailing_slash(resource));
    00040     http::plugin_service *service_ptr;
    00041     service_ptr = m_services.load(clean_resource, service_name);
    00042     http::server::add_resource(clean_resource, boost::ref(*service_ptr));
    00043     service_ptr->set_resource(clean_resource);
    00044     PION_LOG_INFO(m_logger, "Loaded web service plug-in for resource (" << clean_resource << "): " << service_name);
    00045 }
    00046
    00047 void plugin_server::set_service_option(const std::string& resource,
    00048                                  const std::string& name, const std::string& value)
    00049 {
    00050     const std::string clean_resource(strip_trailing_slash(resource));
    00051     m_services.run(clean_resource, boost::bind(&http::plugin_service::set_option, _1, name, value));
    00052     PION_LOG_INFO(m_logger, "Set web service option for resource ("
    00053                   << resource << "): " << name << '=' << value);
    00054 }
    00055
    00056 void plugin_server::load_service_config(const std::string& config_name)
    00057 {
    00058     std::string config_file;
    00059     if (! plugin::find_config_file(config_file, config_name))
    00060         BOOST_THROW_EXCEPTION( error::file_not_found() << error::errinfo_file_name(config_name) );
    00061
    00062     // open the file for reading
    00063     std::ifstream config_stream;
    00064     config_stream.open(config_file.c_str(), std::ios::in);
    00065     if (! config_stream.is_open())
    00066         BOOST_THROW_EXCEPTION( error::open_file() << error::errinfo_file_name(config_name) );
    00067
    00068     // parse the contents of the file
    00069     http::auth_ptr my_auth_ptr;
    00070     enum ParseState {
    00071         PARSE_NEWLINE, PARSE_COMMAND, PARSE_RESOURCE, PARSE_VALUE, PARSE_COMMENT, PARSE_USERNAME
    00072     } parse_state = PARSE_NEWLINE;
    00073     std::string command_string;
    00074     std::string resource_string;
    00075     std::string username_string;
    00076     std::string value_string;
    00077     std::string option_name_string;
    00078     std::string option_value_string;
    00079     int c = config_stream.get();    // read the first character
    00080
    00081     while (config_stream) {
    00082         switch(parse_state) {
    00083         case PARSE_NEWLINE:
    00084             // parsing command portion (or beginning of line)
    00085             if (c == '#') {
    00086                 // line is a comment
    00087                 parse_state = PARSE_COMMENT;
    00088             } else if (isalpha(c)) {
    00089                 // first char in command
    00090                 parse_state = PARSE_COMMAND;
    00091                 // ignore case for commands
    00092                 command_string += tolower(c);
    00093             } else if (c != '\r' && c != '\n') {    // check for blank lines
    00094                 BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00095             }
    00096             break;
    00097
    00098         case PARSE_COMMAND:
    00099             // parsing command portion (or beginning of line)
    00100             if (c == ' ' || c == '\t') {
    00101                 // command finished -> check if valid
    00102                 if (command_string=="path" || command_string=="auth" || command_string=="restrict") {
    00103                     value_string.clear();
    00104                     parse_state = PARSE_VALUE;
    00105                 } else if (command_string=="service" || command_string=="option") {
    00106                     resource_string.clear();
    00107                     parse_state = PARSE_RESOURCE;
    00108                 } else if (command_string=="user") {
    00109                     username_string.clear();
    00110                     parse_state = PARSE_USERNAME;
    00111                 } else {
    00112                     BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00113                 }
    00114             } else if (! isalpha(c)) {
    00115                 // commands may only contain alpha chars
    00116                 BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00117             } else {
    00118                 // ignore case for commands
    00119                 command_string += tolower(c);
    00120             }
    00121             break;
    00122
    00123         case PARSE_RESOURCE:
    00124             // parsing resource portion (/hello)
    00125             if (c == ' ' || c == '\t') {
    00126                 // check for leading whitespace
    00127                 if (! resource_string.empty()) {
    00128                     // resource finished
    00129                     value_string.clear();
    00130                     parse_state = PARSE_VALUE;
    00131                 }
    00132             } else if (c == '\r' || c == '\n') {
    00133                 // line truncated before value
    00134                 BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00135             } else {
    00136                 // add char to resource
    00137                 resource_string += c;
    00138             }
    00139             break;
    00140
    00141         case PARSE_USERNAME:
    00142             // parsing username for user command
    00143             if (c == ' ' || c == '\t') {
    00144                 // check for leading whitespace
    00145                 if (! username_string.empty()) {
    00146                     // username finished
    00147                     value_string.clear();
    00148                     parse_state = PARSE_VALUE;
    00149                 }
    00150             } else if (c == '\r' || c == '\n') {
    00151                 // line truncated before value (missing username)
    00152                 BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00153             } else {
    00154                 // add char to username
    00155                 username_string += c;
    00156             }
    00157             break;
    00158
    00159         case PARSE_VALUE:
    00160             // parsing value portion
    00161             if (c == '\r' || c == '\n') {
    00162                 // value is finished
    00163                 if (value_string.empty()) {
    00164                     // value must not be empty
    00165                     BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00166                 } else if (command_string == "path") {
    00167                     // finished path command
    00168                     try { plugin::add_plugin_directory(value_string); }
    00169                     catch (std::exception& e) {
    00170                         PION_LOG_WARN(m_logger, boost::diagnostic_information(e));
    00171                     }
    00172                 } else if (command_string == "auth") {
    00173                     // finished auth command
    00174                     user_manager_ptr user_mgr(new user_manager);
    00175                     if (value_string == "basic"){
    00176                         my_auth_ptr.reset(new http::basic_auth(user_mgr));
    00177                     }
    00178                     else if (value_string == "cookie"){
    00179                         my_auth_ptr.reset(new http::cookie_auth(user_mgr));
    00180                     }
    00181                     else {
    00182                         // only basic and cookie authentications are supported
    00183                         BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00184                     }
    00185                 } else if (command_string == "restrict") {
    00186                     // finished restrict command
    00187                     if (! my_auth_ptr)
    00188                         // Authentication type must be defined before restrict
    00189                         BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00190                     else if (value_string.empty())
    00191                         // No service defined for restrict parameter
    00192                         BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00193                     my_auth_ptr->add_restrict(value_string);
    00194                 } else if (command_string == "user") {
    00195                     // finished user command
    00196                     if (! my_auth_ptr)
    00197                         // Authentication type must be defined before users
    00198                         BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00199                     else if (value_string.empty())
    00200                         // No password defined for user parameter
    00201                         BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00202                     my_auth_ptr->add_user(username_string, value_string);
    00203                 } else if (command_string == "service") {
    00204                     // finished service command
    00205                     load_service(resource_string, value_string);
    00206                 } else if (command_string == "option") {
    00207                     // finished option command
    00208                     std::string::size_type pos = value_string.find('=');
    00209                     if (pos == std::string::npos)
    00210                         BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
    00211                     option_name_string = value_string.substr(0, pos);
    00212                     option_value_string = value_string.substr(pos + 1);
    00213                     set_service_option(resource_string, option_name_string,
    00214                                      option_value_string);
    00215                 }
    00216                 command_string.clear();
    00217                 parse_state = PARSE_NEWLINE;
    00218             } else if (c == ' ' || c == '\t') {
    00219                 // only skip leading whitespace (value may contain spaces, etc)
    00220                 if (! value_string.empty())
    00221                     value_string += c;
    00222             } else {
    00223                 // add char to value
    00224                 value_string += c;
    00225             }
    00226             break;
    00227
    00228         case PARSE_COMMENT:
    00229             // skipping comment line
    00230             if (c == '\r' || c == '\n')
    00231                 parse_state = PARSE_NEWLINE;
    00232             break;
    00233         }
    00234
    00235         // read the next character
    00236         c = config_stream.get();
    00237     }
    00238
    00239     // update authentication configuration for the server
    00240     set_authentication(my_auth_ptr);
    00241 }
    00242
    00243 }   // end namespace http
    00244 }   // end namespace pion