~ubuntu-branches/debian/sid/pion/sid

« back to all changes in this revision

Viewing changes to src/http_plugin_server.cpp

  • Committer: Package Import Robot
  • Author(s): Roberto C. Sanchez
  • Date: 2013-07-06 18:04:35 UTC
  • Revision ID: package-import@ubuntu.com-20130706180435-kejjzc1qpyz3qv6c
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------------------
 
2
// pion:  a Boost C++ framework for building lightweight HTTP interfaces
 
3
// ---------------------------------------------------------------------
 
4
// Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
 
5
//
 
6
// Distributed under the Boost Software License, Version 1.0.
 
7
// See http://www.boost.org/LICENSE_1_0.txt
 
8
//
 
9
 
 
10
#include <boost/exception/diagnostic_information.hpp>
 
11
#include <pion/error.hpp>
 
12
#include <pion/http/plugin_server.hpp>
 
13
#include <pion/http/request.hpp>
 
14
#include <pion/http/request_reader.hpp>
 
15
#include <pion/http/response_writer.hpp>
 
16
#include <pion/http/basic_auth.hpp>
 
17
#include <pion/http/cookie_auth.hpp>
 
18
#include <fstream>
 
19
 
 
20
 
 
21
namespace pion {    // begin namespace pion
 
22
namespace http {    // begin namespace http
 
23
 
 
24
 
 
25
// plugin_server member functions
 
26
 
 
27
void plugin_server::add_service(const std::string& resource, http::plugin_service *service_ptr)
 
28
{
 
29
    plugin_ptr<http::plugin_service> plugin_ptr;
 
30
    const std::string clean_resource(strip_trailing_slash(resource));
 
31
    service_ptr->set_resource(clean_resource);
 
32
    m_services.add(clean_resource, service_ptr);
 
33
    http::server::add_resource(clean_resource, boost::ref(*service_ptr));
 
34
    PION_LOG_INFO(m_logger, "Loaded static web service for resource (" << clean_resource << ")");
 
35
}
 
36
 
 
37
void plugin_server::load_service(const std::string& resource, const std::string& service_name)
 
38
{
 
39
    const std::string clean_resource(strip_trailing_slash(resource));
 
40
    http::plugin_service *service_ptr;
 
41
    service_ptr = m_services.load(clean_resource, service_name);
 
42
    http::server::add_resource(clean_resource, boost::ref(*service_ptr));
 
43
    service_ptr->set_resource(clean_resource);
 
44
    PION_LOG_INFO(m_logger, "Loaded web service plug-in for resource (" << clean_resource << "): " << service_name);
 
45
}
 
46
 
 
47
void plugin_server::set_service_option(const std::string& resource,
 
48
                                 const std::string& name, const std::string& value)
 
49
{
 
50
    const std::string clean_resource(strip_trailing_slash(resource));
 
51
    m_services.run(clean_resource, boost::bind(&http::plugin_service::set_option, _1, name, value));
 
52
    PION_LOG_INFO(m_logger, "Set web service option for resource ("
 
53
                  << resource << "): " << name << '=' << value);
 
54
}
 
55
 
 
56
void plugin_server::load_service_config(const std::string& config_name)
 
57
{
 
58
    std::string config_file;
 
59
    if (! plugin::find_config_file(config_file, config_name))
 
60
        BOOST_THROW_EXCEPTION( error::file_not_found() << error::errinfo_file_name(config_name) );
 
61
    
 
62
    // open the file for reading
 
63
    std::ifstream config_stream;
 
64
    config_stream.open(config_file.c_str(), std::ios::in);
 
65
    if (! config_stream.is_open())
 
66
        BOOST_THROW_EXCEPTION( error::open_file() << error::errinfo_file_name(config_name) );
 
67
    
 
68
    // parse the contents of the file
 
69
    http::auth_ptr my_auth_ptr;
 
70
    enum ParseState {
 
71
        PARSE_NEWLINE, PARSE_COMMAND, PARSE_RESOURCE, PARSE_VALUE, PARSE_COMMENT, PARSE_USERNAME
 
72
    } parse_state = PARSE_NEWLINE;
 
73
    std::string command_string;
 
74
    std::string resource_string;
 
75
    std::string username_string;
 
76
    std::string value_string;
 
77
    std::string option_name_string;
 
78
    std::string option_value_string;
 
79
    int c = config_stream.get();    // read the first character
 
80
    
 
81
    while (config_stream) {
 
82
        switch(parse_state) {
 
83
        case PARSE_NEWLINE:
 
84
            // parsing command portion (or beginning of line)
 
85
            if (c == '#') {
 
86
                // line is a comment
 
87
                parse_state = PARSE_COMMENT;
 
88
            } else if (isalpha(c)) {
 
89
                // first char in command
 
90
                parse_state = PARSE_COMMAND;
 
91
                // ignore case for commands
 
92
                command_string += tolower(c);
 
93
            } else if (c != '\r' && c != '\n') {    // check for blank lines
 
94
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
95
            }
 
96
            break;
 
97
            
 
98
        case PARSE_COMMAND:
 
99
            // parsing command portion (or beginning of line)
 
100
            if (c == ' ' || c == '\t') {
 
101
                // command finished -> check if valid
 
102
                if (command_string=="path" || command_string=="auth" || command_string=="restrict") {
 
103
                    value_string.clear();
 
104
                    parse_state = PARSE_VALUE;
 
105
                } else if (command_string=="service" || command_string=="option") {
 
106
                    resource_string.clear();
 
107
                    parse_state = PARSE_RESOURCE;
 
108
                } else if (command_string=="user") {
 
109
                    username_string.clear();
 
110
                    parse_state = PARSE_USERNAME;
 
111
                } else {
 
112
                    BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
113
                }
 
114
            } else if (! isalpha(c)) {
 
115
                // commands may only contain alpha chars
 
116
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
117
            } else {
 
118
                // ignore case for commands
 
119
                command_string += tolower(c);
 
120
            }
 
121
            break;
 
122
 
 
123
        case PARSE_RESOURCE:
 
124
            // parsing resource portion (/hello)
 
125
            if (c == ' ' || c == '\t') {
 
126
                // check for leading whitespace
 
127
                if (! resource_string.empty()) {
 
128
                    // resource finished
 
129
                    value_string.clear();
 
130
                    parse_state = PARSE_VALUE;
 
131
                }
 
132
            } else if (c == '\r' || c == '\n') {
 
133
                // line truncated before value
 
134
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
135
            } else {
 
136
                // add char to resource
 
137
                resource_string += c;
 
138
            }
 
139
            break;
 
140
        
 
141
        case PARSE_USERNAME:
 
142
            // parsing username for user command
 
143
            if (c == ' ' || c == '\t') {
 
144
                // check for leading whitespace
 
145
                if (! username_string.empty()) {
 
146
                    // username finished
 
147
                    value_string.clear();
 
148
                    parse_state = PARSE_VALUE;
 
149
                }
 
150
            } else if (c == '\r' || c == '\n') {
 
151
                // line truncated before value (missing username)
 
152
                BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
153
            } else {
 
154
                // add char to username
 
155
                username_string += c;
 
156
            }
 
157
            break;
 
158
        
 
159
        case PARSE_VALUE:
 
160
            // parsing value portion
 
161
            if (c == '\r' || c == '\n') {
 
162
                // value is finished
 
163
                if (value_string.empty()) {
 
164
                    // value must not be empty
 
165
                    BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
166
                } else if (command_string == "path") {
 
167
                    // finished path command
 
168
                    try { plugin::add_plugin_directory(value_string); }
 
169
                    catch (std::exception& e) {
 
170
                        PION_LOG_WARN(m_logger, boost::diagnostic_information(e));
 
171
                    }
 
172
                } else if (command_string == "auth") {
 
173
                    // finished auth command
 
174
                    user_manager_ptr user_mgr(new user_manager);
 
175
                    if (value_string == "basic"){
 
176
                        my_auth_ptr.reset(new http::basic_auth(user_mgr));
 
177
                    }
 
178
                    else if (value_string == "cookie"){
 
179
                        my_auth_ptr.reset(new http::cookie_auth(user_mgr));
 
180
                    }
 
181
                    else {
 
182
                        // only basic and cookie authentications are supported
 
183
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
184
                    }
 
185
                } else if (command_string == "restrict") {
 
186
                    // finished restrict command
 
187
                    if (! my_auth_ptr)
 
188
                        // Authentication type must be defined before restrict
 
189
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
190
                    else if (value_string.empty())
 
191
                        // No service defined for restrict parameter
 
192
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
193
                    my_auth_ptr->add_restrict(value_string);
 
194
                } else if (command_string == "user") {
 
195
                    // finished user command
 
196
                    if (! my_auth_ptr)
 
197
                        // Authentication type must be defined before users
 
198
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
199
                    else if (value_string.empty())
 
200
                        // No password defined for user parameter
 
201
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
202
                    my_auth_ptr->add_user(username_string, value_string);
 
203
                } else if (command_string == "service") {
 
204
                    // finished service command
 
205
                    load_service(resource_string, value_string);
 
206
                } else if (command_string == "option") {
 
207
                    // finished option command
 
208
                    std::string::size_type pos = value_string.find('=');
 
209
                    if (pos == std::string::npos)
 
210
                        BOOST_THROW_EXCEPTION( error::bad_config() << error::errinfo_file_name(config_name) );
 
211
                    option_name_string = value_string.substr(0, pos);
 
212
                    option_value_string = value_string.substr(pos + 1);
 
213
                    set_service_option(resource_string, option_name_string,
 
214
                                     option_value_string);
 
215
                }
 
216
                command_string.clear();
 
217
                parse_state = PARSE_NEWLINE;
 
218
            } else if (c == ' ' || c == '\t') {
 
219
                // only skip leading whitespace (value may contain spaces, etc)
 
220
                if (! value_string.empty())
 
221
                    value_string += c;
 
222
            } else {
 
223
                // add char to value
 
224
                value_string += c;
 
225
            }
 
226
            break;
 
227
        
 
228
        case PARSE_COMMENT:
 
229
            // skipping comment line
 
230
            if (c == '\r' || c == '\n')
 
231
                parse_state = PARSE_NEWLINE;
 
232
            break;
 
233
        }
 
234
 
 
235
        // read the next character
 
236
        c = config_stream.get();
 
237
    }
 
238
    
 
239
    // update authentication configuration for the server
 
240
    set_authentication(my_auth_ptr);
 
241
}
 
242
 
 
243
}   // end namespace http
 
244
}   // end namespace pion