wibble  0.1.28
http.h
Go to the documentation of this file.
00001 #ifndef WIBBLE_NET_HTTP_H
00002 #define WIBBLE_NET_HTTP_H
00003 
00004 /*
00005  * net/http - HTTP server utilities
00006  *
00007  * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00022  */
00023 
00024 #include <string>
00025 #include <map>
00026 #include <wibble/regexp.h>
00027 #include <wibble/net/mime.h>
00028 #include <iosfwd>
00029 #include <stdexcept>
00030 
00031 namespace wibble {
00032 namespace net {
00033 namespace http {
00034 
00035 struct Request;
00036 
00037 struct error : public std::exception
00038 {
00039     int code;
00040     std::string desc;
00041     std::string msg;
00042 
00043     error(int code, const std::string& desc)
00044         : code(code), desc(desc) {}
00045     error(int code, const std::string& desc, const std::string& msg)
00046         : code(code), desc(desc), msg(msg) {}
00047     virtual ~error() throw () {}
00048 
00049     virtual const char* what() const throw ();
00050 
00051     virtual void send(Request& req);
00052 };
00053 
00054 struct error400 : public error
00055 {
00056     error400() : error(400, "Bad request") {}
00057     error400(const std::string& msg) : error(400, "Bad request", msg) {}
00058 };
00059 
00060 struct error404 : public error
00061 {
00062     error404() : error(404, "Not found") {}
00063     error404(const std::string& msg) : error(404, "Not found", msg) {}
00064 
00065     virtual void send(Request& req);
00066 };
00067 
00068 struct Request
00069 {
00070     // Request does not take ownership of the socket: it is up to the caller to
00071     // close it
00072     int sock;
00073     std::string peer_hostname;
00074     std::string peer_hostaddr;
00075     std::string peer_port;
00076     std::string server_name;
00077     std::string server_port;
00078     std::string script_name;
00079     std::string path_info;
00080     std::string query_string;
00082     std::string server_software;
00084     bool response_started;
00085 
00086     std::string method;
00087     std::string url;
00088     std::string version;
00089     std::map<std::string, std::string> headers;
00090     wibble::Splitter space_splitter;
00091 
00092     wibble::net::mime::Reader mime_reader;
00093 
00094     std::map<std::string, std::string> extra_response_headers;
00095 
00096     Request();
00097 
00112     bool read_request();
00113 
00120     bool read_buf(std::string& res, size_t size);
00121 
00122     // Read HTTP method and its following empty line
00123     bool read_method();
00124 
00131     bool read_headers();
00132 
00137     void set_cgi_env();
00138 
00140     void send(const std::string& buf);
00141 
00143     void send_status_line(int code, const std::string& msg, const std::string& version = "HTTP/1.0");
00144 
00146     void send_server_header();
00147 
00149     void send_date_header();
00150 
00152     void send_extra_response_headers();
00153 
00155     void send_result(const std::string& content, const std::string& content_type="text/html; charset=utf-8", const std::string& filename=std::string());
00156 
00158     void discard_input();
00159 
00166     std::string pop_path_info();
00167 
00173     std::string path_info_head();
00174 };
00175 
00177 struct Param
00178 {
00179     virtual ~Param();
00180 
00187     virtual void parse(const std::string& str) = 0;
00188 };
00189 
00191 struct ParamSingle : public std::string, public Param
00192 {
00193     virtual void parse(const std::string& str);
00194 };
00195 
00197 struct ParamMulti : public std::vector<std::string>, public Param
00198 {
00199     virtual void parse(const std::string& str);
00200 };
00201 
00205 struct FileParam
00206 {
00208     struct FileInfo
00209     {
00211         std::string fname;
00213         std::string client_fname;
00214 
00218         bool read(net::mime::Reader& mime_reader,
00219               std::map<std::string, std::string> headers,
00220               const std::string& outdir,
00221               const std::string& fname_blacklist,
00222               const std::string& client_fname,
00223               int sock,
00224               const std::string& boundary,
00225               size_t inputsize);
00226     };
00227 
00228     virtual ~FileParam();
00229 
00233     virtual bool read(
00234             net::mime::Reader& mime_reader,
00235             std::map<std::string, std::string> headers,
00236             const std::string& outdir,
00237             const std::string& fname_blacklist,
00238             const std::string& client_fname,
00239             int sock,
00240             const std::string& boundary,
00241             size_t inputsize) = 0;
00242 };
00243 
00247 struct FileParamSingle : public FileParam
00248 {
00249     FileInfo info;
00250 
00255     FileParamSingle(const std::string& fname=std::string());
00256 
00257     virtual bool read(
00258             net::mime::Reader& mime_reader,
00259             std::map<std::string, std::string> headers,
00260             const std::string& outdir,
00261             const std::string& fname_blacklist,
00262             const std::string& client_fname,
00263             int sock,
00264             const std::string& boundary,
00265             size_t inputsize);
00266 };
00267 
00271 struct FileParamMulti : public FileParam
00272 {
00273     std::vector<FileInfo> files;
00274 
00275     virtual bool read(
00276             net::mime::Reader& mime_reader,
00277             std::map<std::string, std::string> headers,
00278             const std::string& outdir,
00279             const std::string& fname_blacklist,
00280             const std::string& client_fname,
00281             int sock,
00282             const std::string& boundary,
00283             size_t inputsize);
00284 };
00285 
00292 struct Params : public std::map<std::string, Param*>
00293 {
00295     std::map<std::string, FileParam*> files;
00296 
00298     size_t conf_max_input_size;
00299 
00301     size_t conf_max_field_size;
00302 
00310     bool conf_accept_unknown_fields;
00311 
00319     bool conf_accept_unknown_file_fields;
00320 
00326     std::string conf_outdir;
00327 
00335     std::string conf_fname_blacklist;
00336 
00337 
00338     Params();
00339     ~Params();
00340 
00342     template<typename TYPE>
00343     TYPE* add(const std::string& name)
00344     {
00345         TYPE* res = new TYPE;
00346         add(name, res);
00347         return res;
00348     }
00349 
00351     void add(const std::string& name, Param* param);
00352 
00354     void add(const std::string& name, FileParam* param);
00355 
00361     Param* obtain_field(const std::string& name);
00362 
00368     FileParam* obtain_file_field(const std::string& name);
00369 
00371     Param* field(const std::string& name);
00372 
00374     FileParam* file_field(const std::string& name);
00375 
00377     void parse_get_or_post(net::http::Request& req);
00378 
00380     void parse_urlencoded(const std::string& qstring);
00381 
00383     void parse_multipart(net::http::Request& req, size_t inputsize, const std::string& content_type);
00384 
00386     void parse_post(net::http::Request& req);
00387 };
00388 
00389 
00390 }
00391 }
00392 }
00393 
00394 // vim:set ts=4 sw=4:
00395 #endif