Boost logo

Boost-Commit :

From: lists.drrngrvy_at_[hidden]
Date: 2008-08-04 17:17:03


Author: drrngrvy
Date: 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
New Revision: 47978
URL: http://svn.boost.org/trac/boost/changeset/47978

Log:
Adding several fixes from a while ago (ike);
Plus, some fixes from Christian Leutloff (see http://tinyurl.com/5cz67a)
Added:
   sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/basic_request.ipp (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/boost/cgi/utility/redirect.hpp (contents, props changed)
Properties modified:
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/ (props changed)
Text files modified:
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp | 10 +++---
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp | 42 +++++++++++++++++++++++++++++++
   sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp | 6 ++--
   sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp | 1
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp | 4 +-
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/save_environment.hpp | 10 ++++++-
   sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp | 8 +++---
   sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2 | 53 ++++++++++++++++++++++++++++++++++++++-
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2 | 20 +++++++-------
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk | 2
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp | 12 +++-----
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp | 23 +++++++++-------
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 | 7 ++++
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp | 3 -
   sandbox/SOC/2007/cgi/trunk/libs/cgi/test/Jamfile.v2 | 2
   sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/request_test_template.hpp | 42 ++++++++++++++++---------------
   sandbox/SOC/2007/cgi/trunk/project-root.jam | 1
   17 files changed, 176 insertions(+), 70 deletions(-)

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/parse_options.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -7,12 +7,12 @@
 
    enum parse_options
    {
- parse_none = 0 // you should *always* parse the environment!
+ parse_none = 0 // you should *always* parse the environment.
      , parse_env = 1
- , parse_get = 2
- , parse_post = 4
- , parse_form = parse_get | parse_post
- , parse_cookie = 8
+ , parse_get = 2 | parse_env
+ , parse_post = 4 | parse_env
+ , parse_form = parse_env | parse_get | parse_post
+ , parse_cookie = 8 | parse_env
      , parse_all = parse_env | parse_form | parse_cookie
    };
 

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/request_base.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -19,6 +19,7 @@
 #include <boost/system/error_code.hpp>
 ////////////////////////////////////////////////////////////////
 #include "boost/cgi/common/map.hpp"
+#include "boost/cgi/common/parse_options.hpp"
 #include "boost/cgi/detail/extract_params.hpp"
 
 namespace cgi {
@@ -84,6 +85,47 @@
       return impl.client_.read_some(buf,ec);
     }
 
+ /// Synchronously read/parse the request meta-data
+ template<typename ImplType>
+ boost::system::error_code
+ load(ImplType& impl, common::parse_options parse_opts
+ , boost::system::error_code& ec)
+ {
+ if (parse_opts & common::parse_env)
+ {
+ if (!read_env_vars(impl, ec)) // returns an error_code
+ return ec;
+ }
+
+ std::string const& cl = env_vars(impl.vars_)["CONTENT_LENGTH"];
+ impl.characters_left_ = cl.empty() ? 0 : boost::lexical_cast<std::size_t>(cl);
+ impl.client_.bytes_left() = impl.characters_left_;
+
+ std::string const& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
+
+ if (request_method == "GET" && parse_opts & common::parse_get)
+ {
+ parse_get_vars(impl, ec);
+ }
+ else
+ if (request_method == "POST" && parse_opts & common::parse_post)
+ {
+ parse_post_vars(impl, ec);
+ }
+
+ if (ec) return ec;
+
+ if (parse_opts & common::parse_cookie)
+ {
+ if (!parse_cookie_vars(impl, ec)) // returns an error_code
+ return ec;
+ }
+
+ set_status(impl, common::loaded);
+
+ return ec;
+ }
+
     /// Read and parse the cgi GET meta variables
     template<typename ImplType>
     boost::system::error_code

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/shareable_tcp_socket.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -50,7 +50,7 @@
     typedef boost::mutex mutex_type;
     struct condition_type : public boost::condition_variable
         { typedef boost::shared_ptr<boost::condition_variable> pointer; };
- typedef boost::unique_lock<mutex_type> scoped_lock_type;
+ typedef boost::mutex::scoped_lock scoped_lock_type;
     typedef boost::asio::ip::tcp::socket next_layer_type;
 
     /** FastCGI specific stuff **/
@@ -93,13 +93,13 @@
 
     void lock()
     {
- scoped_lock_type(mutex_);
+ scoped_lock_type lock(mutex_);
       locked_ = true;
     }
 
     void unlock()
     {
- scoped_lock_type(mutex_);
+ scoped_lock_type lock(mutex_);
       locked_ = false;
       condition_.notify_one();
     }

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -17,6 +17,7 @@
 ///////////////////////////////////////////////////////////
 #include "boost/cgi/error.hpp"
 #include "boost/cgi/common/tags.hpp"
+#include "boost/cgi/basic_connection.hpp"
 #include "boost/cgi/common/connection_base.hpp"
 #include "boost/cgi/fwd/basic_connection_fwd.hpp"
 

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -124,7 +124,7 @@
       impl.http_status() = http_s;
       return status;
     }
-
+/*
     /// Synchronously read/parse the request meta-data
     boost::system::error_code&
     load(implementation_type& impl, common::parse_options parse_opts
@@ -164,7 +164,7 @@
 
       return ec;
     }
-
+*/
     /// Synchronously read/parse the request meta-data
     /**
      * @param parse_stdin if true then STDIN data is also read/parsed

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/save_environment.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/save_environment.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/save_environment.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -17,7 +17,7 @@
 // The process' environment
 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
   // MSVC warns of 'inconsistent dll linkage' here...
- _CRTIMP extern char** environ;
+ _CRTIMP extern char** _environ;
 #else
   extern char** environ;
 #endif
@@ -32,7 +32,13 @@
     * environment.
     */
    template<typename MapT>
- void save_environment(MapT& env_map, char** env = environ)
+ void save_environment(MapT& env_map, char** env =
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
+ _environ
+#else
+ environ
+#endif
+ )
    {
      std::string sa;
      std::string sb;

Added: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/basic_request.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/basic_request.ipp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -0,0 +1,505 @@
+// -- basic_request.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+//
+// Defines the basic_request<> class; the main entry-point to the
+// library.
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_BASIC_REQUEST_HPP_INCLUDED__
+#define CGI_BASIC_REQUEST_HPP_INCLUDED__
+
+#include "boost/cgi/detail/push_options.hpp"
+
+#include <boost/mpl/if.hpp>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/basic_io_object.hpp>
+///////////////////////////////////////////////////////////
+// **FIXME** Half of these are probably useless
+#include "boost/cgi/detail/protocol_traits.hpp"
+#include "boost/cgi/common/map.hpp"
+#include "boost/cgi/common/is_async.hpp"
+#include "boost/cgi/common/role_type.hpp"
+#include "boost/cgi/http/status_code.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/common/status_type.hpp"
+#include "boost/cgi/common/source_enums.hpp"
+#include "boost/cgi/fwd/basic_request_fwd.hpp"
+#include "boost/cgi/common/request_service.hpp"
+#include "boost/cgi/import/basic_io_object.hpp"
+#include "boost/cgi/detail/basic_sync_io_object.hpp"
+#include "boost/cgi/fwd/basic_protocol_service_fwd.hpp"
+
+namespace cgi {
+ namespace common {
+
+ /// The basic_request class, primary entry point to the library
+ /**
+ * Note: By default, synchronous protocols (ie. cgi) auto-load AND parse
+ * STDIN,whereas async protocols don't.
+ *
+ * Note: The alternative functions which take a boost::system::error_code are
+ * the non-throwing versions. Instead of a boost::system::system_error being
+ * thrown in case of an error, the passed error_code will be set to the value
+ * of the error, s.t. if (error) evaluates to true.`
+ *
+ * Note: This class isn't thread safe: carrying around a mutex-per-request
+ * seems prohibitively expensive. There could be functions which take a mutex
+ * as an arguement and lock it. (Async calls could get messy if you need a
+ * protected request object).
+ **/
+
+ // Throws
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>::basic_request
+ (
+ bool load_now = true, bool parse_post = true
+ )
+ : detail::basic_sync_io_object<service_type>()
+ {
+ if (load_now) load(parse_post);
+ }
+
+ // Won't throw
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>::basic_request
+ (
+ boost::system::error_code& ec
+ , const bool load_now = true
+ , const bool parse_post = true
+ )
+ : detail::basic_sync_io_object<service_type>()
+ {
+ if (load_now) load(ec, parse_post);
+ }
+
+ // Throws
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>::basic_request
+ (
+ protocol_service_type& s, const bool load_now = false
+ , const bool parse_post = false
+ )
+ : basic_io_object<service_type>(s.io_service())
+ {
+ set_protocol_service(s);
+ if (load_now) load(parse_post);
+ }
+
+ // Won't throw
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>::basic_request
+ (
+ protocol_service_type& s
+ , boost::system::error_code& ec
+ , const bool load_now = false, const bool parse_post = false
+ )
+ : basic_io_object<service_type>(s.io_service())
+ {
+ set_protocol_service(s);
+ if(load_now) load(ec, parse_post);//this->service.load(this->implementation, false, ec);
+ }
+
+ /// Make a new mutiplexed request from an existing connection.
+ // Throws.
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>:: basic_request(implementation_type& impl)
+ : basic_io_object<service_type>(impl.service_->io_service())
+ {
+ set_protocol_service(*impl.service_);
+ boost::system::error_code ec;
+ this->service.begin_request_helper(this->implementation
+ , impl.header_buf_, ec);
+ detail::throw_error(ec);
+ }
+
+ /// Make a new mutiplexed request from an existing connection.
+ // Won't throw.
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>:: basic_request(implementation_type& impl, boost::system::error_code& ec)
+ : basic_io_object<service_type>(impl.service_->io_service())
+ {
+ set_protocol_service(*impl.service_);
+ this->service.begin_request_helper(this->implementation
+ , impl.header_buf_, ec);
+ }
+
+ ~basic_request()
+ {
+ //if (is_open())
+ // close(http::internal_server_error, 0);
+ }
+
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>:: static pointer create(protocol_service_type& ps)
+ {
+ return pointer(new type(ps));
+ }
+
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>:: void set_protocol_service(protocol_service_type& ps)
+ {
+ this->service.set_service(this->implementation, ps);
+ }
+
+ /// Return `true` if the request is still open (ie. not aborted or closed)
+ template<typename RS, typename PS, typename A>
+ basic_request<RS,PS,A>:: bool is_open()
+ {
+ return this->service.is_open(this->implementation);
+ }
+
+ /// Synchronously read/parse the request meta-data
+ /**
+ * Note: 'loading' including reading/parsing STDIN if parse_stdin == true
+ */
+ // Throwing semantics
+ void load(bool parse_stdin = false)
+ {
+ boost::system::error_code ec;
+ this->service.load(this->implementation, parse_stdin, ec);
+ detail::throw_error(ec);
+ }
+
+ // Error-code semantics (**FIXME**)
+ boost::system::error_code&
+ load(bool parse_stdin, boost::system::error_code& ec)
+ {
+ return this->service.load(this->implementation, parse_stdin, ec);
+ }
+
+ // Error-code semantics (**FIXME**)
+ boost::system::error_code&
+ load(boost::system::error_code& ec, bool parse_stdin = false)
+ {
+ return this->service.load(this->implementation, parse_stdin, ec);
+ }
+
+ buffer_type& get_buffer()
+ {
+ return this->implementation.buffer_;
+ }
+
+ // **FIXME**
+ /// Asynchronously read/parse the request meta-data
+ /**
+ * Note: 'loading' including reading/parsing STDIN if parse_stdin == true
+ */
+ //template<typename Handler>
+ //void async_load(Handler handler, bool parse_stdin = false)
+ //{
+ // this->service.async_load(this->implementation, parse_stdin
+ // , handler);
+ //}
+
+ /// Notify the server the request has finished being handled
+ /**
+ * In certain situations (such as a Proactor client using the async read
+ * functions) it will be necessary to call end, rather than just returning
+ * from the sub_main function.
+ *
+ * @param program_status This value is returned to the server indicating the
+ * state of the request after it was finished handling. It is
+ * implementation defined how the server deals with this, and it may have
+ * no effect on the http status code returned to the client (eg. 200 OK).
+ *
+ * @returns The value of program_status
+ */
+ int close(common::http::status_code http_status = http::ok
+ , int program_status = 0)
+ {
+ //BOOST_ASSERT( request_status_ != status_type::ended );
+
+ //this->service.set_status(this->implementation, http_status);
+ boost::system::error_code ec;
+ this->service.close(this->implementation, http_status,
+ program_status, ec);
+ detail::throw_error(ec);
+ return program_status;
+ }
+
+ int close(common::http::status_code http_status
+ , int program_status
+ , boost::system::error_code& ec)
+ {
+ return this->service.close(this->implementation, http_status
+ , program_status, ec);
+ }
+
+ /// Reject the request with a standard '500 Internal Server Error' error
+ int reject()
+ {
+ this->service.set_status(this->implementation, aborted);
+ return this->service.close(this->implementation
+ , http::internal_server_error);
+ }
+
+ /// Abort a request
+ void abort()
+ {
+ this->service.set_status(this->implementation, aborted);
+ }
+
+ /// Clear the data for the request, for reusing this object.
+ // I'd imagine clearing and re-loading a request is quicker than
+ // destroying/re-creating one. **Unverified claims** **FIXME**
+ void clear()
+ {
+ this->service.clear(this->implementation);
+ }
+
+ /// Get the client connection associated with the request
+ /**
+ * You use the client for read/write calls. Y
+ */
+ client_type& client()
+ {
+ return this->service.client(this->implementation);
+ }
+
+ /// Read some data into the request, parsing if necessary.
+ void read_some()
+ {
+ boost::system::error_code ec;
+ this->service.read_some(this->implementation, ec);
+ detail::throw_error(ec);
+ }
+
+ /// Read some data into the request, parsing if necessary.
+ std::size_t
+ read_some(boost::system::error_code& ec)
+ {
+ return this->service.read_some(this->implementation, ec);
+ }
+
+ /// Read some data into the supplied buffer, parsing if necessary.
+ // **FIXME** (remove - use req.client().read_some() instead)
+ template<typename MutableBufferSequence>
+ void read_some(const MutableBufferSequence& buf)
+ {
+ boost::system::error_code ec;
+ this->service.read_some(this->implementation, buf, ec);
+ detail::throw_error(ec);
+ }
+
+ /// Read some data into the supplied buffer, parsing if necessary.
+ // **FIXME** (remove - use req.client().read_some() instead)
+ template<typename MutableBufferSequence>
+ std::size_t
+ read_some(const MutableBufferSequence& buf
+ , boost::system::error_code& ec)
+ {
+ return this->service.read_some(this->implementation, buf, ec);
+ }
+
+ /// Set the output for the request
+ /**
+ * Not Implemented Yet ******************
+ *
+ * Set the output sink as `stdout_`, `stderr_`, or `stdout_ | stderr_`
+ */
+ /*
+ void set_output(cgi::sink dest, boost::system::error_code& ec)
+ {
+ this->service(this->implementation, dest, ec);
+ }
+ */
+
+ // [helper-functions for the basic CGI 1.1 meta-variables.
+ string_type& auth_type()
+ { return env_("AUTH_TYPE"); }
+
+ string_type& content_length()
+ { return env_("CONTENT_LENGTH"); }
+
+ string_type& content_type()
+ { return env_("CONTENT_TYPE"); }
+
+ string_type& gateway_interface()
+ { return env_("GATEWAY_INTERFACE"); }
+
+ string_type& path_info()
+ { return env_("PATH_INFO"); }
+
+ string_type& path_translated()
+ { return env_("PATH_TRANSLATED"); }
+
+ string_type& query_string()
+ { return env_("QUERY_STRING"); }
+
+ string_type& remote_addr()
+ { return env_("REMOTE_ADDR"); }
+
+ string_type& remote_host()
+ { return env_("REMOTE_HOST"); }
+
+ string_type& remote_ident()
+ { return env_("REMOTE_IDENT"); }
+
+ string_type& remote_user()
+ { return env_("REMOTE_USER"); }
+
+ string_type& request_method()
+ { return env_("REQUEST_METHOD"); }
+
+ string_type& script_name()
+ { return env_("SCRIPT_NAME"); }
+
+ string_type& server_name()
+ { return env_("SERVER_NAME"); }
+
+ string_type& server_port()
+ { return env_("SERVER_PORT"); }
+
+ string_type& server_protocol()
+ { return env_("SERVER_PROTOCOL"); }
+
+ string_type& server_software()
+ { return env_("SERVER_SOFTWARE"); }
+
+ string_type& referer()
+ { return env_("HTTP_REFERER"); }
+ // -- end helper-functions]
+
+ /// Get the charset from the CONTENT_TYPE header
+ string_type charset()
+ {
+ // Not sure if regex is needlessly heavy-weight here.
+ boost::regex re(";[ ]?charset=([-\\w]+);");
+ boost::smatch match;
+ if (!boost::regex_match(this->content_type(), match, re))
+ return ""; // A default could go here.
+
+ return match[1];
+ }
+
+ /// The role that the request is playing
+ /**
+ * The default role type is responder.
+ *
+ * In some cases - for instance with FastCGI - the role type can be
+ * different
+ * eg. authorizer, or filter.
+ */
+ role_type& role()
+ {
+ return this->service.get_role(this->implementation);
+ }
+
+ void set_status(common::http::status_code const& status)
+ {
+ this->service.set_status(this->implementation, status);
+ }
+
+ ////////////////////////////////////////////////////////////
+ // Note on operator[]
+ // ------------------
+ // It is overloaded on different enum types to allow
+ // compile-time (I hope) retrieval of different data
+ // maps.
+ //
+
+ // The first three overloads are for directly looking into the
+ // environment.
+ // eg.
+ // string_type& val = req["some name"];
+
+ /// Get the value of the environment variable with name `n`.
+ string_type& operator[](string_type const& n)
+ {
+ return env_vars(this->implementation.vars_)[n.c_str()];
+ }
+
+ /// Get the value of the environment variable with name `n`.
+ string_type& operator[](const char* n)
+ {
+ return env_vars(this->implementation.vars_)[n];
+ }
+
+ /// Get the value of the environment variable with name `n`.
+ string_type& operator[](common::name const& n)
+ {
+ return env_vars(this->implementation.vars_)[n];
+ }
+
+ /// Get a `common::env_map&` of all the environment variables.
+ env_map& operator[](common::env_data_type const&)
+ {
+ return env_vars(this->implementation.vars_);
+ }
+
+ /// Get a `common::get_map&` of all the GET variables.
+ get_map& operator[](common::get_data_type const&)
+ {
+ return get_vars(this->implementation.vars_);
+ }
+
+ /// Get a `common::post_map&` of all the POST variables.
+ post_map& operator[](common::post_data_type const&)
+ {
+ return post_vars(this->implementation.vars_);
+ }
+
+ /// Get a `common::cookie_map&` of all the cookies.
+ cookie_map& operator[](common::cookie_data_type const&)
+ {
+ return cookie_vars(this->implementation.vars_);
+ }
+
+ /// Get a `common::form_map&` of either the GET or POST variables.
+ form_map& operator[](common::form_data_type const&)
+ {
+ if (request_method() == "GET")
+ return get_vars(this->implementation.vars_);
+ else
+ if (request_method() == "POST")
+ return post_vars(this->implementation.vars_);
+ else
+ return env_vars(this->implementation.vars_);
+ }
+ ////////////////////////////////////////////////////////////
+
+ /// The id of this request.
+ /**
+ * This is 1 for CGI/aCGI requests, but may be != 1 for FastCGI requests.
+ * Note that for FastCGI requests, the id's are assigned on a
+ * *per-connection* policy, so in one application you may have several
+ * requests with the same id.
+ */
+ int id()
+ {
+ return this->service.request_id(this->implementation);
+ }
+
+ private:
+ // Internal shortcut for named env-var functions (eg. script_name() above).
+ string_type& env_(const char* name)
+ {
+ return env_vars(this->implementation.vars_)[name];
+ }
+ };
+
+ } // namespace common
+} // namespace cgi
+
+#include "boost/cgi/detail/pop_options.hpp"
+
+#endif // CGI_BASIC_REQUEST_HPP_INCLUDED__
+
+/*
+NOTES::future_plans:
+* When a request is aborted (eg. when the client closes the connection)
+ the library can call an abort_handler() function stored in the request.
+ - The user should supply an abort_handler-derived function if they want
+ any special handling of aborted requests
+*/
+

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -120,7 +120,7 @@
      * packet for this request arrives from the server.
      *
      */
-
+/*
     /// Synchronously read/parse the request meta-data
     BOOST_CGI_INLINE boost::system::error_code
     fcgi_request_service::load(
@@ -129,7 +129,7 @@
     {
       if (parse_opts & common::parse_env)
       {
- if (read_env_vars(impl, ec)) // returns an error_code
+ if (!read_env_vars(impl, ec)) // returns an error_code
           return ec;
       }
 
@@ -153,7 +153,7 @@
 
       if (parse_opts & common::parse_cookie)
       {
- if (parse_cookie_vars(impl, ec)) // returns an error_code
+ if (!parse_cookie_vars(impl, ec)) // returns an error_code
           return ec;
       }
 
@@ -161,7 +161,7 @@
 
       return ec;
     }
-
+*/
     BOOST_CGI_INLINE boost::system::error_code
     fcgi_request_service::load(
         implementation_type& impl, bool parse_stdin

Added: sandbox/SOC/2007/cgi/trunk/boost/cgi/utility/redirect.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/utility/redirect.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_CGI_REDIRECT_HPP_INCLUDED_
+#define BOOST_CGI_REDIRECT_HPP_INCLUDED_
+
+#include <string>
+///////////////////////////////////////////////////////////
+#include <boost/system/error_code.hpp>
+///////////////////////////////////////////////////////////
+#include "boost/cgi/write.hpp"
+#include "boost/cgi/header.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+
+namespace cgi {
+ namespace common {
+
+ /// Redirect a request to another place.
+ template <typename RequestT>
+ boost::system::error_code
+ redirect(RequestT& req, typename RequestT::string_type const& dest
+ , boost::system::error_code& ec)
+ {
+ basic_header<typename RequestT::char_type> hdr("Location", dest);
+ write(req.client(), buffer(hdr.content), ec);
+ return ec;
+ }
+
+ template <typename RequestT>
+ void redirect(RequestT& req, std::string const& dest)
+ {
+ boost::system::error_code ec;
+ redirect(req, dest, ec);
+ detail::throw_error(ec);
+ }
+
+ } // namespace common
+} // namespace cgi
+
+#endif // BOOST_CGI_REDIRECT_HPP_INCLUDED_
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -8,6 +8,46 @@
   DEFINES = <define>BOOST_CGI_BUILD_LIB ;
 }
 
+# --------------------------------
+rule tag ( name : type ? : property-set )
+{
+ if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
+ {
+ if $(layout) = versioned
+ {
+ local result = [ common.format-name
+ <base> <toolset> <threading> <runtime> # -$(BOOST_VERSION_TAG)
+ # -$(BUILD_ID)
+ : $(name) : $(type) : $(property-set) ] ;
+
+ # Optionally add version suffix.
+ # On NT, library with version suffix won't be recognized
+ # by linkers. On CYGWIN, we get strage duplicate symbol
+ # errors when library is generated with version suffix.
+ # On OSX, version suffix is not needed -- the linker expets
+ # libFoo.1.2.3.dylib format.
+ # AIX linkers don't accept version suffixes either.
+ # Pgi compilers can't accept library with version suffix
+ #if $(type) = SHARED_LIB &&
+ # ( ! ( [ $(property-set).get <target-os> ] in windows cygwin darwin aix ) &&
+ # ! ( [ $(property-set).get <toolset> ] in pgi ) )
+ #{
+ # result = $(result).$(BOOST_VERSION) ;
+ #}
+
+ return $(result) ;
+ }
+ else
+ {
+ return [ common.format-name
+ <base> <threading> <runtime> # -$(BUILD_ID)
+ : $(name) : $(type) : $(property-set) ] ;
+ }
+ }
+}
+
+# --------------------------------
+
 project boost/cgi
   : build-dir
       $(top)/bin.v2
@@ -17,6 +57,7 @@
       <library>/boost/thread/
       <library>/boost/system/
       <library>/boost/regex/
+ <library>/boost/date_time/
       <define>_CRT_SECURE_NO_WARNINGS
       <define>_SCL_SECURE_NO_WARNINGS
       $(DEFINES)
@@ -26,7 +67,11 @@
       <library>/boost/thread/
       <library>/boost/system/
       <library>/boost/regex/
- <linkflags>-pthread
+ <library>/boost/date_time/
+ <define>_CRT_SECURE_NO_WARNINGS
+ <define>_SCL_SECURE_NO_WARNINGS
+ <os>unix:<linkflags>-pthread
+ #<tag>@$(__name__).tag
       $(DEFINES)
   ;
 
@@ -34,7 +79,7 @@
 { # compile library
   ECHO "Building CGI library" ;
 
- # make BB recognise .ipp files as .cpp files.
+ # make BB recognise .ipp files as .cpp (source) files.
   import type ;
   type.register IPP : ipp : CPP ;
 
@@ -50,6 +95,10 @@
 else
 {
   alias boost_cgi ;
+
+ # make BB recognise .ipp files as .hpp (header) files.
+ import type ;
+ type.register IPP : ipp : HPP ;
 }
 
 install install

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/Jamfile.v2 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -6,9 +6,9 @@
 #project boost.cgi.docs
 # ;
 
-#import boostbook : boostbook ;
-import quickbook ;
+import boostbook : boostbook ;
 import doxygen ;
+import quickbook ;
 
 # compile the doxygen sources here
 doxygen autodoc
@@ -33,10 +33,10 @@
 
     [ glob ../../../boost/cgi/connections/*.hpp ]
   :
- #<doxygen.processor>doxproc
- #<doxygen.doxproc.index>yes
- #<doxygen.doxproc.title>"Developer Reference"
- #<doxygen.doxproc.id>"developer_reference"
+ <doxygen.processor>doxproc
+ <doxygen.doxproc.index>yes
+ <doxygen.doxproc.title>"Developer Reference"
+ <doxygen.doxproc.id>"developer_reference"
 
     <doxygen:param>HIDE_UNDOC_MEMBERS=NO
     <doxygen:param>EXTRACT_PRIVATE=NO
@@ -75,8 +75,8 @@
     #<xsl:param>chunk.section.depth=2 # chunk
          ;
 
-#install html
-# :
-# /boost//doc/html/boostbook.css
+install html
+ :
+ /boost//doc/html/boostbook.css
 # /bin/doc/$(toolset)/debug/cgi_xml.xml
-# ;
+ ;

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -78,7 +78,7 @@
 ]
 
 [important
-This manual does [*not] document a library that is a part of __Boost__. The major part of it has been developed this summer as part of the Google Summer of Code, '[@http://code.google.com/soc GSoC07]'. Everything from here on in is alpha-grade, some bits more than others; [link boost.cgi.preface.comments_and_support comments and bug reports] are welcome.
+This manual does [*not] document a library that is a part of __Boost__. The major part of it has been developed this summer as part of the Google Summer of Code, '[@http://code.google.com/soc/2007 GSoC07]'. Everything from here on in is alpha-grade, some bits more than others; [link boost.cgi.preface.comments_and_support comments and bug reports] are welcome.
 
 These documents are either hosted at [@http://sourceforge.net/projects/cgi/ sourceforge], or at [@http://svn.boost.org/svn/boost/browser/sandbox/SOC/2007/cgi svn.boost.org]. For free!
 ]

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/10_min_intro.cpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -12,9 +12,9 @@
   request req;
 
 /*`
-At this point, the environment variables are accessible. This includes cookie and form variables too, which by default are all parsed.
+At this point, the environment variables are accessible. This includes cookie and form variables too, which by default are all parsed (this is optional).
 
-The `response` class provides a streaming interface for writing replies. You ['can] write to the request object directly, but for now we're going to just use the `response`, which is simpler. Writing to a `response` is buffered - whereas writing to the request directly isn't - so if an error occurs, you can simply `clear()` the response and send an error message, which is much cleaner than sending half a response to the client, followed by "... Sorry, I just broke!".
+The `response` class provides a streaming interface for writing replies. You ['can] write to the request object directly, but for now we're going to just use the `response`, which works well for most situations. Writing to a `response` is buffered - whereas writing to the request directly isn't - so if an error occurs, you can simply `clear()` the response and send an error message, which is much cleaner than sending half a response to the client, followed by "... Sorry, I just broke!".
 */
 
   response resp;
@@ -23,7 +23,7 @@
 Let's assume you now want to check if the user has a cookie, "user_name", set. We get at it like this:
 */
 
- std::string user_name( req.cookie_("user_name") );
+ std::string user_name( req[cookie]["user_name"] );
 
 /*`
 If it's set, we'll be polite and say hello. If you are used to CGI programming, you'll notice the lack of any HTTP headers. If you don't want to bother with headers, a default header `'Content-type: text/plain'` is sent, followed by the usual HTTP end-of-line `'\r\n'` and a blank line which indicates the end of the headers and the start of content.
@@ -45,7 +45,7 @@
 /*`
 If the cookie isn't set, we will check if the user has posted a __GET__/__POST__ form with their name.
 */
- user_name = req.form_("user_name");
+ user_name = req[form]["user_name"];
 
   if (!user_name.empty())
   {
@@ -60,18 +60,16 @@
     resp<< cookie("user_name", user_name)
         << header("Date", "Tue, 15 Nov 1994 08:12:31 GMT")
         << header("Content-type", "text/plain")
- << header() // this terminates the headers
         << "Hello there, " << user_name << ". You're new around here.";
 
     resp.send(req);
   }
 
 /*`
-Now, if we have no idea who they are, we'll send a form asking them for their name. As the default `"Content-type"` header is `"text/plain"`, we'll change this to `"text/html"` so the user's browser will display the HTML form. You can do this using `req.set_header("Content-type", "text/html")` or `resp<< header("Content-type", "text/html")`. Since writing with raw strings is error-prone, the shortcut below is available.
+Now, if we have no idea who they are, we'll send a form asking them for their name. As the default `"Content-type"` header is `"text/plain"`, we'll change this to `"text/html"` so the user's browser will display the HTML form. You can do this using `set_header(req, "Content-type", "text/html")` or `resp<< header("Content-type", "text/html")`. Since writing with raw strings is error-prone, the shortcut below is available.
 */
 
   resp<< content_type("text/html")
- << header() // remember to end the headers
       << "Hello there. What's your name?" "<p />"
          "<form method='POST'>"
          "<input type='text' name='user_name' />"

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -93,7 +93,7 @@
     try {
 
       boost::system::error_code ec;
- req.load(ec, true);
+ req.load(ec, parse_all); // parse everything.
 
       if (ec)
       {
@@ -130,19 +130,22 @@
                  "<input type=submit value=submit />"
                "</form><p />";
 
- format_map(resp, req[env], "Environment Variables");
- format_map(resp, req[get], "GET Variables");
- format_map(resp, req[post], "POST Variables");
+ format_map(resp, req[env], "Environment Variables");
+ format_map(resp, req[get], "GET Variables");
+ format_map(resp, req[post], "POST Variables");
       format_map(resp, req[cookies], "Cookie Variables");
 
- resp<< "<pre>";
- BOOST_FOREACH(char& ch, req.post_buffer())
+ if (req["request_method"] = "GET")
       {
- resp<< ch;
+ resp<< "<pre>";
+ BOOST_FOREACH(char& ch, req.post_buffer())
+ {
+ resp<< ch;
+ }
+ resp<< "</pre>"
+ "</body>"
+ "</html>";
       }
- resp<< "</pre>"
- "</body>"
- "</html>";
 
       return_(resp, req, 0); // All ok.
 

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -6,7 +6,12 @@
 
 project boost/cgi/example/cgi/hello_world ;
 
-exe cgi_hello_world : main.cpp /boost/regex/ ;
+exe cgi_hello_world
+ :
+ main.cpp /boost/regex/ /boost/cgi/
+ :
+ ;
+
 
 # Our install rule (builds binaries and copies them to <location>)
 install install

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/main.cpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -152,8 +152,7 @@
   //
   resp<< "Response content-length == "
       << resp.content_length() // the content-length (returns std::size_t)
- << content_length(resp) // a content-length header
- << ">";
+ << content_length(resp); // a content-length header
 
   // This funky macro finishes up:
   return_(resp, req, 0);

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/test/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/test/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/test/Jamfile.v2 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -2,7 +2,7 @@
 
 project
   : requirements
- <include>$(BOOST_ROOT)
+ <include>$(boost-root)
       <include>../../../
       # suppress annoying MSVC warnings
       <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/request_test_template.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/request_test_template.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/test/run/request_test_template.hpp 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -3,13 +3,13 @@
                                                                                  \
   /* Check environment parsing */ \
   BOOST_CHECK( req[env_data].size() ); \
- BOOST_CHECK_EQUAL( req[env_data]["HTTP_HOST"], "localhost" ); \
- BOOST_CHECK_EQUAL( req[env_data]["EMPTY_VAR"], "" ); \
- BOOST_CHECK_EQUAL( req[env_data]["UGLY_VAR"], "$££$^%%£&&^%@%26$ £_abcd" ); \
- BOOST_CHECK_EQUAL( req[env_data]["QUERY_STRING"] \
+ BOOST_CHECK_EQUAL( req[env]["HTTP_HOST"], "localhost" ); \
+ BOOST_CHECK_EQUAL( req[env]["EMPTY_VAR"], "" ); \
+ BOOST_CHECK_EQUAL( req[env]["UGLY_VAR"], "$££$^%%£&&^%@%26$ £_abcd" ); \
+ BOOST_CHECK_EQUAL( req[env]["QUERY_STRING"] \
                    , "hello=world&foo=bar&encoded=%22!%C2%A3$%^$*^hh%%thd@:~" ); \
   /* Check case-insensitive name comparing */ \
- BOOST_CHECK_EQUAL( req[env_data]["http_host"], "localhost" ); \
+ BOOST_CHECK_EQUAL( req[env]["http_host"], "localhost" ); \
   /* Check helper function (need to test them all?) */ \
   BOOST_CHECK_EQUAL( req.script_name(), "some/test/script" );
 
@@ -20,45 +20,47 @@
   BOOST_CHECK_EQUAL( req.request_method(), "GET" ); \
                                                                                 \
   /* Check GET data/query string parsing */ \
- BOOST_CHECK( req[get_data].size() ); \
- BOOST_CHECK_EQUAL( req[get_data]["hello"], "world" ); \
- BOOST_CHECK_EQUAL( req[get_data]["foo"], "bar" ); \
+ BOOST_CHECK( req[get].size() ); \
+ BOOST_CHECK_EQUAL( req[get]["hello"], "world" ); \
+ BOOST_CHECK_EQUAL( req[get]["foo"], "bar" ); \
   /* Case-insensitive check */ \
- BOOST_CHECK_EQUAL( req[get_data]["FOO"], "bar" ); \
+ BOOST_CHECK_EQUAL( req[get]["FOO"], "bar" ); \
   /* Value should be case-sensitive */ \
- BOOST_CHECK_NE( req[get_data]["foo"], "BAR" ); \
+ BOOST_CHECK_NE( req[get]["foo"], "BAR" ); \
   /* Check url-decoding */ \
- BOOST_CHECK_EQUAL( req[get_data]["encoded"], "\"!£$%^$*^hh%%thd@:~" );
+ BOOST_CHECK_EQUAL( req[get]["encoded"], "\"!£$%^$*^hh%%thd@:~" );
 
 
 #define TEST_ONE_COOKIE(req) \
                                                                                 \
     /* Check cookie parsing */ \
- BOOST_CHECK( req[cookie_data].size() ); \
- BOOST_CHECK_EQUAL( req[cookie_data]["foo"], "bar" ); \
+ BOOST_CHECK( req[cookies].size() ); \
+ BOOST_CHECK_EQUAL( req[cookies]["foo"], "bar" ); \
     /* Check case-insensitive name comparing */ \
- BOOST_CHECK_EQUAL( req[cookie_data]["FOO"], "bar" );
+ BOOST_CHECK_EQUAL( req[cookies]["FOO"], "bar" );
 
 #define TEST_TWO_COOKIES(req) \
                                                                                 \
- BOOST_CHECK_EQUAL( req[cookie_data]["foo"], "bar" ); \
- BOOST_CHECK_EQUAL( req[cookie_data]["another_one"], "stuff" );
+ BOOST_CHECK_EQUAL( req[cookies]["foo"], "bar" ); \
+ BOOST_CHECK_EQUAL( req[cookies]["another_one"], "stuff" );
  
 #define TEST_ENCODED_COOKIE(req) \
                                                                                 \
- BOOST_CHECK_EQUAL( req[cookie_data]["foo"], "bar" ); \
- BOOST_CHECK_EQUAL( req[cookie_data]["encoded"], "\"£$%^$*^hh%%thd@:" );
+ BOOST_CHECK_EQUAL( req[cookies]["foo"], "bar" ); \
+ BOOST_CHECK_EQUAL( req[cookies]["encoded"], "\"£$%^$*^hh%%thd@:" );
 
 
 #include <string>
 #include <cstdlib>
 #include <boost/config.hpp>
 
-#ifdef BOOST_MSVC
+#ifdef BOOST_WINDOWS
   // MSVC doesn't support setenv, but it does support putenv
   void setenv(std::string const& name, std::string const& val, int reset = 0)
   {
- if (putenv((name + val).c_str()) != 0)
+
+ //char *envvar = new char["
+ if (0 != _putenv((name + "=" + val).c_str()))
     {
       std::cerr<< "Error adding environment variable." << std::endl;
     }

Modified: sandbox/SOC/2007/cgi/trunk/project-root.jam
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/project-root.jam (original)
+++ sandbox/SOC/2007/cgi/trunk/project-root.jam 2008-08-04 17:17:01 EDT (Mon, 04 Aug 2008)
@@ -136,3 +136,4 @@
 use-project /boost/cgi/ : $(top)/libs/cgi/build ;
 
 project anon : build-dir bin.v2 ;
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk