00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <pion/net/WebServer.hpp>
00011 #include <pion/net/HTTPRequest.hpp>
00012 #include <pion/net/HTTPRequestReader.hpp>
00013 #include <pion/net/HTTPResponseWriter.hpp>
00014 #include <pion/net/HTTPBasicAuth.hpp>
00015 #include <pion/net/HTTPCookieAuth.hpp>
00016 #include <fstream>
00017
00018
00019 namespace pion {
00020 namespace net {
00021
00022
00023
00024
00025 void WebServer::addService(const std::string& resource, WebService *service_ptr)
00026 {
00027 PionPluginPtr<WebService> plugin_ptr;
00028 const std::string clean_resource(stripTrailingSlash(resource));
00029 service_ptr->setResource(clean_resource);
00030
00031
00032 try {
00033 m_services.add(clean_resource, service_ptr);
00034 HTTPServer::addResource(clean_resource, boost::ref(*service_ptr));
00035 } catch (std::exception& e) {
00036 throw WebServiceException(resource, e.what());
00037 }
00038 PION_LOG_INFO(m_logger, "Loaded static web service for resource (" << clean_resource << ")");
00039 }
00040
00041 void WebServer::loadService(const std::string& resource, const std::string& service_name)
00042 {
00043 const std::string clean_resource(stripTrailingSlash(resource));
00044 WebService *service_ptr;
00045
00046
00047 try {
00048 service_ptr = m_services.load(clean_resource, service_name);
00049 HTTPServer::addResource(clean_resource, boost::ref(*service_ptr));
00050 service_ptr->setResource(clean_resource);
00051 } catch (std::exception& e) {
00052 throw WebServiceException(resource, e.what());
00053 }
00054 PION_LOG_INFO(m_logger, "Loaded web service plug-in for resource (" << clean_resource << "): " << service_name);
00055 }
00056
00057 void WebServer::setServiceOption(const std::string& resource,
00058 const std::string& name, const std::string& value)
00059 {
00060
00061
00062 const std::string clean_resource(stripTrailingSlash(resource));
00063 try {
00064 m_services.run(clean_resource, boost::bind(&WebService::setOption, _1, name, value));
00065 } catch (PluginManager<WebService>::PluginNotFoundException&) {
00066 throw ServiceNotFoundException(resource);
00067 } catch (std::exception& e) {
00068 throw WebServiceException(resource, e.what());
00069 }
00070 PION_LOG_INFO(m_logger, "Set web service option for resource ("
00071 << resource << "): " << name << '=' << value);
00072 }
00073
00074 void WebServer::loadServiceConfig(const std::string& config_name)
00075 {
00076 std::string config_file;
00077 if (! PionPlugin::findConfigFile(config_file, config_name))
00078 throw ConfigNotFoundException(config_name);
00079
00080
00081 std::ifstream config_stream;
00082 config_stream.open(config_file.c_str(), std::ios::in);
00083 if (! config_stream.is_open())
00084 throw ConfigParsingException(config_name);
00085
00086
00087 HTTPAuthPtr auth_ptr;
00088 enum ParseState {
00089 PARSE_NEWLINE, PARSE_COMMAND, PARSE_RESOURCE, PARSE_VALUE, PARSE_COMMENT, PARSE_USERNAME
00090 } parse_state = PARSE_NEWLINE;
00091 std::string command_string;
00092 std::string resource_string;
00093 std::string username_string;
00094 std::string value_string;
00095 std::string option_name_string;
00096 std::string option_value_string;
00097 int c = config_stream.get();
00098
00099 while (config_stream) {
00100 switch(parse_state) {
00101 case PARSE_NEWLINE:
00102
00103 if (c == '#') {
00104
00105 parse_state = PARSE_COMMENT;
00106 } else if (isalpha(c)) {
00107
00108 parse_state = PARSE_COMMAND;
00109
00110 command_string += tolower(c);
00111 } else if (c != '\r' && c != '\n') {
00112 throw ConfigParsingException(config_name);
00113 }
00114 break;
00115
00116 case PARSE_COMMAND:
00117
00118 if (c == ' ' || c == '\t') {
00119
00120 if (command_string=="path" || command_string=="auth" || command_string=="restrict") {
00121 value_string.clear();
00122 parse_state = PARSE_VALUE;
00123 } else if (command_string=="service" || command_string=="option") {
00124 resource_string.clear();
00125 parse_state = PARSE_RESOURCE;
00126 } else if (command_string=="user") {
00127 username_string.clear();
00128 parse_state = PARSE_USERNAME;
00129 } else {
00130 throw ConfigParsingException(config_name);
00131 }
00132 } else if (! isalpha(c)) {
00133
00134 throw ConfigParsingException(config_name);
00135 } else {
00136
00137 command_string += tolower(c);
00138 }
00139 break;
00140
00141 case PARSE_RESOURCE:
00142
00143 if (c == ' ' || c == '\t') {
00144
00145 if (! resource_string.empty()) {
00146
00147 value_string.clear();
00148 parse_state = PARSE_VALUE;
00149 }
00150 } else if (c == '\r' || c == '\n') {
00151
00152 throw ConfigParsingException(config_name);
00153 } else {
00154
00155 resource_string += c;
00156 }
00157 break;
00158
00159 case PARSE_USERNAME:
00160
00161 if (c == ' ' || c == '\t') {
00162
00163 if (! username_string.empty()) {
00164
00165 value_string.clear();
00166 parse_state = PARSE_VALUE;
00167 }
00168 } else if (c == '\r' || c == '\n') {
00169
00170 throw AuthConfigException("No username defined for user parameter");
00171 } else {
00172
00173 username_string += c;
00174 }
00175 break;
00176
00177 case PARSE_VALUE:
00178
00179 if (c == '\r' || c == '\n') {
00180
00181 if (value_string.empty()) {
00182
00183 throw ConfigParsingException(config_name);
00184 } else if (command_string == "path") {
00185
00186 try { PionPlugin::addPluginDirectory(value_string); }
00187 catch (std::exception& e) {
00188 PION_LOG_WARN(m_logger, e.what());
00189 }
00190 } else if (command_string == "auth") {
00191
00192 PionUserManagerPtr user_manager(new PionUserManager);
00193 if (value_string == "basic"){
00194 auth_ptr.reset(new HTTPBasicAuth(user_manager));
00195 }
00196 else if (value_string == "cookie"){
00197 auth_ptr.reset(new HTTPCookieAuth(user_manager));
00198 }
00199 else{
00200 throw AuthConfigException("Only basic and cookie authentications are supported");
00201 }
00202 } else if (command_string == "restrict") {
00203
00204 if (! auth_ptr)
00205 throw AuthConfigException("Authentication type must be defined before restrict");
00206 else if (value_string.empty())
00207 throw AuthConfigException("No service defined for restrict parameter");
00208 auth_ptr->addRestrict(value_string);
00209 } else if (command_string == "user") {
00210
00211 if (! auth_ptr)
00212 throw AuthConfigException("Authentication type must be defined before users");
00213 else if (value_string.empty())
00214 throw AuthConfigException("No password defined for user parameter");
00215 auth_ptr->addUser(username_string, value_string);
00216 } else if (command_string == "service") {
00217
00218 loadService(resource_string, value_string);
00219 } else if (command_string == "option") {
00220
00221 std::string::size_type pos = value_string.find('=');
00222 if (pos == std::string::npos)
00223 throw ConfigParsingException(config_name);
00224 option_name_string = value_string.substr(0, pos);
00225 option_value_string = value_string.substr(pos + 1);
00226 setServiceOption(resource_string, option_name_string,
00227 option_value_string);
00228 }
00229 command_string.clear();
00230 parse_state = PARSE_NEWLINE;
00231 } else if (c == ' ' || c == '\t') {
00232
00233 if (! value_string.empty())
00234 value_string += c;
00235 } else {
00236
00237 value_string += c;
00238 }
00239 break;
00240
00241 case PARSE_COMMENT:
00242
00243 if (c == '\r' || c == '\n')
00244 parse_state = PARSE_NEWLINE;
00245 break;
00246 }
00247
00248
00249 c = config_stream.get();
00250 }
00251
00252
00253 setAuthentication(auth_ptr);
00254 }
00255
00256 }
00257 }
00258