Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50926 - in sandbox/SOC/2007/cgi/branches/pickmeup: boost/cgi boost/cgi/common boost/cgi/detail boost/cgi/fcgi boost/cgi/impl boost/cgi/utility libs/cgi/build/msvc libs/cgi/build/msvc/9.0 libs/cgi/build/msvc/9.0/Boost.CGI libs/cgi/build/msvc/9.0/Boost.CGI/Amortization libs/cgi/build/msvc/9.0/Boost.CGI/acgi_cookie_game libs/cgi/build/msvc/9.0/Boost.CGI/acgi_echo libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world libs/cgi/build/msvc/9.0/Boost.CGI/cgi_ctemplate_debug_server libs/cgi/build/msvc/9.0/Boost.CGI/cgi_debug_server libs/cgi/build/msvc/9.0/Boost.CGI/cgi_echo libs/cgi/build/msvc/9.0/Boost.CGI/cgi_hello_world libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_hello_world libs/cgi/build/msvc/9.0/Boost.CGI/xcgi_server1 libs/cgi/doc/src/user_guide/tutorial libs/cgi/example/acgi/amortization libs/cgi/example/acgi/cookie_game libs/cgi/example/acgi/echo libs/cgi/example/cgi libs/cgi/example/cgi/DebugServer libs/cgi/example/cgi/DebugServer2 libs/cgi/example/cgi/hello_world libs/cgi/example/xcgi/server1 libs/cgi/src libs/cgi/test/run
From: lists.drrngrvy_at_[hidden]
Date: 2009-01-31 07:18:47


Author: drrngrvy
Date: 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
New Revision: 50926
URL: http://svn.boost.org/trac/boost/changeset/50926

Log:
Adding msvc projects. These are set up for my system, you will need to include some directories in your environment, such as:
* The Google cTemplate header/libs paths (only needed for some examples)
* This library's Header Files in your path
* The Boost library's header/lib files
 --------------------
Other changes include:
* Bug fixes
* The utility/*.hpp helper functions
* See the diffs (sorry...)
Added:
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/get_value.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/has_key.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Amortization/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Amortization/Amortization.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Amortization/Amortization.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.ncb (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.sln (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.suo (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_cookie_game/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_cookie_game/acgi_cookie_game.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_cookie_game/acgi_cookie_game.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_echo/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_echo/acgi_echo.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_echo/acgi_echo.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_ctemplate_debug_server/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_ctemplate_debug_server/cgi_ctemplate_debug_server.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_ctemplate_debug_server/cgi_ctemplate_debug_server.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_debug_server/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_debug_server/cgi_debug_server.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_debug_server/cgi_debug_server.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_echo/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_echo/cgi_echo.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_echo/cgi_echo.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_hello_world/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_hello_world/cgi_hello_world.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_hello_world/cgi_hello_world.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_hello_world/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_hello_world/fcgi_hello_world.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_hello_world/fcgi_hello_world.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/xcgi_server1/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/xcgi_server1/xcgi_server1.vcproj (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/xcgi_server1/xcgi_server1.vcproj.360-SYSTEMS.darreng.user (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/acgi_amort.html (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/Jamfile.v2 (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/Timer.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/TracingServer.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/TracingServer.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/hello.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/TracebackServer.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/TracebackServer.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/ctemplate.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.css (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.html (contents, props changed)
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.js (contents, props changed)
Removed:
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/acgi_amort.tpl
Text files modified:
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_connection.hpp | 65 --------
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp | 35 +++-
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/cookie.hpp | 19 +
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/name.hpp | 4
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/parse_options.hpp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/path_info.hpp | 18 +-
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/request_base.hpp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp | 26 ++
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/cgi_service_impl_base.hpp | 10
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/common_headers.hpp | 2
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/extract_params.hpp | 24 +-
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/save_environment.hpp | 16 +
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/url_decode.ipp | 9
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/error.hpp | 101 -------------
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor.hpp | 2
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor_service_impl.hpp | 53 +++---
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp | 7
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/form_parser.ipp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp | 49 ++++++
   sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/redirect.hpp | 28 ++-
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/doc/src/user_guide/tutorial/quickstart.qbk | 23 ++
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/main.cpp | 72 +++++++--
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/cookie_game/main.cpp | 291 ++++++++++++++++++++++++++++++---------
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/echo/main.cpp | 2
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/Jamfile.v2 | 2
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/hello_world/main.cpp | 3
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/xcgi/server1/Server.hpp | 1
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/src/library_sources.cpp | 5
   sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/test/run/request_test_template.hpp | 10
   32 files changed, 537 insertions(+), 370 deletions(-)

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_client.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -67,6 +67,11 @@
       connection_->close();
     }
 
+ boost::uint16_t const& request_id() const
+ {
+ return 1;
+ }
+
     /// Associate a connection with this client
     /**
      * Note: the connection must have been created using the new operator

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_connection.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_connection.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_connection.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -9,77 +9,12 @@
 #ifndef CGI_BASIC_CONNECTION_HPP_INCLUDED__
 #define CGI_BASIC_CONNECTION_HPP_INCLUDED__
 
-//#include <istream>
-//#include <ostream>
-//#include <boost/asio.hpp>
-
-//#include "boost/cgi/tags.hpp"
-//#include "boost/cgi/connection_base.hpp"
-//#include "connections/async_stdio_connection_impl.hpp"
-
 namespace cgi {
  namespace common {
 
   template<typename ConnectionType>
   class basic_connection;
 
-/*
- : public connection_base
- //, connection_wrapper<ConnectionType>
- {
- public:
- // typedef ConnectionType impl_type;
- // //typedef boost::shared_ptr<conection_base> pointer;
-
- // explicit basic_connection(protocol_service_type& ps)
- // : impl_(ps)
- // {
- // }
-
- // static pointer create()
- // {
- // return new basic_connection<protocol_service_type
- // , connection_type>(impl_.protocol_service());
- // }
-
- //private:
- // impl_type impl_;
- };
-
-*/
-
- // template<typename ProtocolService>
- //class async_stdio_connection_impl;
-
- //template<typename ProtocolService>
- //class stdio_connection_impl;
-
-
- //#include "connections/stdio_connection_impl.hpp"
-
- //template<typename ProtocolService>
- // class basic_connection<tags::stdio, ProtocolService>
- // : public stdio_connection_impl<ProtocolService>
- //{
- //};
-
- //typedef basic_connection<tags::stdio, stdio_connection
-
-
- //#include "connections/async_stdio_connection_impl.hpp"
-
- //template<typename ProtocolService>
- //class basic_connection<tags::async_stdio, ProtocolService>
- // : public async_stdio_connection_impl<ProtocolService>
- //{
- //};
-
- //typedef basic_connection<tags::tcp> tcp_connection;
- //typedef basic_connection<tags::pipe> pipe_connection; // not implemented
-//#include "connections/stdio_connection.hpp"
-//#include "connections/async_stdio_connection.hpp"
-//#include "connections/tcp_connection.hpp"
-
  } // namespace common
 } // namespace cgi
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/basic_request.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -84,39 +84,50 @@
     typedef typename implementation_type::buffer_type buffer_type;
 
 
+ /*
     // Throws
- basic_request(bool load_now = true, bool parse_post = true)
+ basic_request(bool load_now, bool parse_post = true)
       : detail::basic_sync_io_object<service_type>()
     {
       if (load_now) load(parse_post);//this->service.load(this->implementation, true, ec);
     }
+ */
 
- // Won't throw
+ basic_request(const parse_options opts = parse_none)
+ : detail::basic_sync_io_object<service_type>()
+ {
+ if (opts > parse_none) load(opts);//this->service.load(this->implementation, true, ec);
+ }
+
+ // Won't throw
     basic_request(boost::system::error_code& ec
                  , const bool load_now = true
- , const bool parse_post = true)
+ , const bool parse_post_now = true)
       : detail::basic_sync_io_object<service_type>()
     {
- if (load_now) load(ec, parse_post);//this->service.load(this->implementation, true, ec);
+ const parse_options opts = parse_post_now ? parse_post : parse_env;
+ if (load_now) load(opts, ec);//this->service.load(this->implementation, true, ec);
     }
 
                 // Throws
     basic_request(protocol_service_type& s, const bool load_now = false
- , const bool parse_post = false)
+ , const bool parse_post_now = false)
       : basic_io_object<service_type>(s.io_service())
     {
       set_protocol_service(s);
- if (load_now) load(parse_post);//this->service.load(this->implementation, false, ec);
+ const parse_options opts = parse_post_now ? parse_post : parse_env;
+ if (load_now) load(opts);//this->service.load(this->implementation, false, ec);
     }
 
                 // Won't throw
     basic_request(protocol_service_type& s
                  , boost::system::error_code& ec
- , const bool load_now = false, const bool parse_post = false)
+ , const bool load_now = false, const bool parse_post_now = 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);
+ const parse_options opts = parse_post_now ? parse_post : parse_env;
+ if(load_now) load(opts, ec);//this->service.load(this->implementation, false, ec);
     }
 
     /// Make a new mutiplexed request from an existing connection.
@@ -168,10 +179,10 @@
      * Note: 'loading' including reading/parsing STDIN if parse_stdin == true
      */
     // Throwing semantics
- void load(bool parse_stdin = false)
+ void load(parse_options parse_opts = parse_env)
     {
       boost::system::error_code ec;
- this->service.load(this->implementation, parse_stdin, ec);
+ this->service.load(this->implementation, parse_opts, ec);
       detail::throw_error(ec);
     }
 
@@ -181,7 +192,7 @@
     {
       return this->service.load(this->implementation, parse_opts, ec);
     }
-
+/*
     // Error-code semantics (**FIXME**)
     boost::system::error_code
       load(bool parse_stdin, boost::system::error_code& ec)
@@ -195,7 +206,7 @@
     {
       return this->service.load(this->implementation, parse_stdin, ec);
     }
-
+*/
     /// Get the buffer containing the POST data.
     /**
      * **FIXME**

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/cookie.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/cookie.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/cookie.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -13,11 +13,13 @@
 #include <boost/system/error_code.hpp>
 #include <boost/tokenizer.hpp>
 
+#define BOOST_CGI_DATE_IN_THE_PAST "Fri, 05-Jun-1989 15:30:00 GMT"
+
 namespace cgi {
  namespace common {
 
   template<typename CharT> struct basic_cookie;
-
+
   // typedefs for common usage
   typedef basic_cookie<char> cookie;
   typedef basic_cookie<wchar_t> wcookie;
@@ -41,11 +43,11 @@
 
     basic_cookie() {}
 
- /// Delete the cookie named `_name`.
+ /// Create a cookie for deleting the cookie named `_name`.
     basic_cookie(const string_type& _name)
       : name(_name)
       , value()
- , expires("Fri, 05-Jun-1989 15:30:00 GMT")
+ , expires(BOOST_CGI_DATE_IN_THE_PAST)
       , path("/")
       , secure(false)
       , http_only(false)
@@ -103,13 +105,15 @@
     static basic_cookie<string_type> from_string(const char* str)
     {
       boost::system::error_code ec;
- cookie ck = from_string(ec);
+ basic_cookie<string_type> ck = from_string(ec);
       detail::throw_error(ec);
       return ck;
     }
 
     static basic_cookie<string_type> from_string(std::string& str)
     {
+ basic_cookie<string_type> ck;
+ std::string val""
       return from_string(str.c_str());
     }
 
@@ -136,13 +140,14 @@
  } // namespace common
 } // namespace cgi
 
-
-template<typename OutStream, typename T>
-inline OutStream& operator<< (OutStream& os, cgi::common::basic_cookie<T> const& ck)
+/*
+template<typename OutStream, typename CharT>
+inline OutStream& operator<< (OutStream& os, cgi::common::basic_cookie<CharT> const& ck)
 {
   os<< ck.to_string();
   return os;
 }
+*/
 
 #endif // CGI_COOKIE_HPP_INCLUDED__
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/name.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/name.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/name.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -61,7 +61,7 @@
 
    };
 
- // typedef for typical usage.
+ // typedefs for typical usage.
    typedef std::basic_string<char, ichar_traits<char> > name;
    typedef std::basic_string<wchar_t, ichar_traits<wchar_t> > wname;
 
@@ -72,7 +72,7 @@
                , std::basic_string<CharT, ichar_traits<CharT> > const& str)
   {
     return os<< str.c_str();
- }
+ }
 
  } // namespace common
 } // namespace cgi

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/parse_options.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/parse_options.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/parse_options.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -5,9 +5,12 @@
 namespace cgi {
  namespace common {
 
+ // Parser options for loading requests. Note that you should *always*
+ // parse the environment before using a request object. If you don't parse
+ // anything you will have unspecified behaviour.
    enum parse_options
    {
- parse_none = 0 // you should *always* parse the environment.
+ parse_none = 0
      , parse_env = 1
      , parse_get = 2 | parse_env
      , parse_post = 4 | parse_env

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/path_info.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/path_info.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/path_info.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -10,27 +10,29 @@
 
 namespace cgi {
  namespace common {
-
+
+ namespace algo = boost::string::algorithm;
+
    struct path_info
    {
      typedef std::string value_type;
      typedef std::vector<value_type> vector_type;
      typedef vector_type::iterator iterator;
-
+
      template<typename S, typename P, typename A>
      path_info(basic_request<S,P,A> & request)
- : value(boost::algorithm::trim_copy_if(request["path_info"],
- boost::algorithm::is_any_of("/")))
+ : value(algo::trim_copy_if(request["path_info"],
+ algo::is_any_of("/")))
      {
- boost::algorithm::split(parts, value, boost::algorithm::is_any_of("/"));
+ algo::split(parts, value, algo::is_any_of("/"));
      }
 
      path_info(value_type const& str)
- : value(boost::algorithm::trim_copy_if(str, boost::algorithm::is_any_of("/")))
+ : value(algo::trim_copy_if(str, algo::is_any_of("/")))
      {
- boost::algorithm::split(parts, value, boost::algorithm::is_any_of("/"));
+ algo::split(parts, value, algo::is_any_of("/"));
      }
-
+
      value_type value;
      vector_type parts;
    };

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/request_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/request_base.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/request_base.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -37,9 +37,9 @@
 
     /// Get the request ID of a FastCGI request, or 1.
     template<typename ImplType>
- int request_id(ImplType& impl)
+ boost::uint16_t const& request_id(ImplType& impl) const
     {
- return impl.client_.request_id_;
+ return impl.client_.request_id();
     }
 
     // impl_base is the common base class for all request types'
@@ -98,6 +98,7 @@
       }
 
       std::string const& cl = env_vars(impl.vars_)["CONTENT_LENGTH"];
+ // This will throw if the content-length isn't a valid number (which shouldn't ever happen).
       impl.characters_left_ = cl.empty() ? 0 : boost::lexical_cast<std::size_t>(cl);
       impl.client_.bytes_left() = impl.characters_left_;
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/response.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -130,7 +130,7 @@
     /// Allow more headers to be added (WARNING: avoid using this).
     void unterminate_headers();
 
- /// Get the length of the body of the response
+ /// Get the length of the body of the response (ie. not including the headers).
     std::size_t content_length();
 
     /// Add a header after appending the CRLF sequence.
@@ -140,7 +140,9 @@
     /// Format and add a header given name and value, appending CRLF.
     basic_response<char_type>&
       set_header(string_type const& name, string_type const& value);
-
+
+ string_type header_value(string_type const& name);
+
     void clear_headers();
 
     void reset_headers();
@@ -152,6 +154,10 @@
 
     /// Get the ostream containing the response body.
     ostream_type& ostream();
+
+ /// Get the headers
+ std::vector<string_type>& headers();
+
   protected:
     // Vector of all the headers, each followed by a CRLF
     std::vector<string_type> headers_;
@@ -163,7 +169,7 @@
 
     http::status_code http_status_;
 
- // True if no more headers can be appended.
+ // True if no more headers can be appended.
     bool headers_terminated_;
 
   private:
@@ -201,15 +207,25 @@
    * library.
    */
   template<typename charT, typename T>
- cgi::common::basic_response<charT>&
+ cgi::common::basic_response<charT>&
     operator<< (cgi::common::basic_response<charT>&
                , cgi::common::basic_cookie<T>&);
-
+/*
+ template<typename charT, typename T>
+ cgi::common::basic_response<charT>&
+ operator<< (cgi::common::basic_response<charT>&
+ , cgi::common::basic_cookie<T> const&);
+*/
   template<typename charT, typename T>
   cgi::common::basic_response<charT>&
     operator<< (cgi::common::basic_response<charT>&
                , cgi::common::http::status_code);
 
+ template<typename charT, typename T>
+ cgi::common::basic_response<charT>&
+ operator<< (cgi::common::basic_response<charT>&
+ , cgi::common::basic_response<charT>&);
+
 #include "boost/cgi/detail/pop_options.hpp"
 
 //#if !defined(BOOST_CGI_BUILD_LIB)

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/cgi_service_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/cgi_service_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/cgi_service_impl_base.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -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
@@ -173,6 +173,8 @@
       load(implementation_type& impl, bool parse_stdin
           , boost::system::error_code& ec)
     {
+ return load(impl, parse_stdin ? parse_all : (parse_env | parse_cookies), ec);
+ }/*
       detail::save_environment(env_vars(impl.vars_));
       std::string const& cl = env_vars(impl.vars_)["CONTENT_LENGTH"];
       impl.characters_left_ = cl.empty() ? 0 : boost::lexical_cast<std::size_t>(cl);
@@ -194,7 +196,7 @@
 
       return ec;
     }
-
+*/
     role_type
     get_role(implementation_type& impl)
     {
@@ -210,7 +212,7 @@
     /// Set the request status
     void set_status(implementation_type& impl, common::request_status status)
     {
- impl.request_status_ = status;
+ impl.status() = status;
     }
 
     std::size_t

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/common_headers.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/common_headers.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/common_headers.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -12,6 +12,8 @@
 // #include all protocol-independent headers only. Protocol-specific
 // headers can just include this after other headers.
 
+#include <iostream> // **FIXME** - only for debugging info
+
 //#include "boost/cgi/logger.hpp"
 #include "boost/cgi/common/map.hpp"
 #include "boost/cgi/import/read.hpp"

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/extract_params.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/extract_params.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/extract_params.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -18,12 +18,19 @@
 namespace cgi {
  namespace detail {
 
- /// Extract name/value pairs from a supplied string buffer
- template<typename Map, typename Separator>
- boost::system::error_code& extract_params(const std::string& input
- , Map& destination
- , const Separator& separator
- , boost::system::error_code& ec)
+ /// Extract name/value pairs from a supplied string buffer.
+ /**
+ * Name / value pairs can be separated by either '&' or ';', and the format
+ * of the name / value pairs is:
+ * <name>=<value>
+ *
+ */
+ template<typename String, typename Map, typename Separator>
+ boost::system::error_code&
+ extract_params(const String& input
+ , Map& destination
+ , const Separator& separator
+ , boost::system::error_code& ec)
    {
      if( input.empty() )
        return ec;// = boost::system::error_code(34, boost::system::errno_ecat);
@@ -38,10 +45,6 @@
         ; iter != toker.end()
         ; ++iter)
      {
-// if( *iter == "%" )
-// {
-// current_token += detail::url_decode( *++iter );
-// }else
        if(*iter == "=")
        {
          name = current_token;
@@ -57,6 +60,7 @@
          current_token = url_decode(*iter);
        }
      }
+ // Save the name if the last n/v pair has no value.
      if( !name.empty() )
        destination[name.c_str()] = current_token;
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/save_environment.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/save_environment.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/save_environment.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -30,6 +30,10 @@
    /**
     * @param env This defaults to `::environ`, or the current process'
     * environment.
+ *
+ * Note: empty variables are not guaranteed to be set by the server, so
+ * we are free to ignore them too. Whether we do or not depends on the
+ * macro: BOOST_CGI_KEEP_EMPTY_VARS
     */
    template<typename MapT>
    void save_environment(MapT& env_map, char** env =
@@ -51,15 +55,21 @@
          if ((*env)[i] == '=')
            break;
 
- // Note: empty variables are not guaranteed to be set by the server, so
- // we are free to ignore them too.
+#if defined(BOOST_CGI_KEEP_EMPTY_VARS) && BOOST_CGI_KEEP_EMPTY_VARS != 0
+ sa.assign(*env, i);
+ if ((*env)[i+1] != '\0')
+ {
+ env_map[sa] = sb.clear();
+ }
+#else
        if ((*env)[i+1] != '\0')
        {
          sa.assign(*env, i);
          sb.assign((*env+i+1), j-i-1);
          env_map[sa.c_str()] = sb;
        }
- }
+#endif
+ }
    }
 
  } // namespace detail

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/url_decode.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/url_decode.ipp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/detail/url_decode.ipp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -18,7 +18,7 @@
    BOOST_CGI_INLINE
    std::string char_to_hex(char const& ch)
    {
- return std::string(); // **FIXME**
+ return std::string(); // **FIXME**
    }
 
    /// Convert two characters into a single, hex-encoded character
@@ -40,7 +40,7 @@
    }
 
    /// Take two characters (a hex sequence) and return a char
- // **DEPRECATED**
+ // **DEPRECATED** (use the above function)
    BOOST_CGI_INLINE
    char url_decode( const char& c1, const char& c2 )
    {
@@ -64,6 +64,9 @@
      typedef std::string string_type; // Ahem.
      string_type result;
 
+ if (str.length() == 0)
+ return str;
+
      for( string_type::const_iterator iter (str.begin()), end (str.end())
         ; iter != end; ++iter )
      {
@@ -83,7 +86,7 @@
            }
            else // we've got a properly encoded hex value.
            {
- char ch = *++iter; // need this because order of function arg
+ char ch = *++iter; // need this because order of function arg
                                 // evaluation is UB.
              result.append(1, hex_to_char(ch, *++iter));
            }

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/error.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/error.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/error.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -19,110 +19,11 @@
 
 #include <string>
 #include <boost/system/error_code.hpp>
+#include "boost/cgi/fcgi/error.hpp"
 
 namespace cgi {
   namespace error {
 
-enum fcgi_errors
-{
- bad_header_type = 1,
-
- /// A packet arrived for a request id that doesn't exist and the packet
- // wasn't a BEGIN_REQUEST record.
- bad_request_id,
-
- /// When trying to write a packet, the client::write_some() call didn't
- // transmit enough data before returning.
- couldnt_write_complete_packet,
-
- // Tried to read/write from/to the client associated to a request when it
- // was closed.
- client_closed,
-
- // Self-explanatory (not much a user can do about this though).
- abort_request_record_recieved_for_invalid_request,
-
- // For now a user has to recognise this error and construct a request
- // themselves. This is an ugly hack.
- multiplexed_request_incoming,
-
- duplicate_request,
-
- // Calling async_accept on a request that hasn't been closed isn't
- // allowed.
- accepting_on_an_open_request,
-
- invalid_socket,
-
- // The CONTENT_TYPE for form data wasn't recognised.
- invalid_form_type,
-
- // Used in basic_connection<tags::stdio>
- // **FIXME**
- broken_pipe,
-
- // **FIXME**
- bad_read
-};
-
- namespace detail {
-
-class fcgi_category
- : public boost::system::error_category
-{
-public:
- const char* name() const { return "fcgi_error"; }
- std::string message(int e) const
- {
- switch(e)
- {
- case client_closed:
- return "You are trying to read from or write to a closed client.";
- case multiplexed_request_incoming:
- return "A new request is pending on this connection (ie. it is "
- "multiplexed). This isn't handled for now. **FIXME**";
- case accepting_on_an_open_request:
- return "You called async_accept before closing a request.";
- default:
- return "(FastCGI) BOOM!!!";
- }
- }
-};
-
- } // namespace detail
-
-inline const boost::system::error_category& get_fcgi_category()
-{
- static detail::fcgi_category instance;
- return instance;
-}
-
-static const boost::system::error_category& fcgi_category
- = ::cgi::error::get_fcgi_category();
-
- } // namespace error
-} // namespace cgi
-
-namespace boost {
- namespace system {
-
- template<> struct is_error_code_enum< ::cgi::error::fcgi_errors>
- {
- BOOST_STATIC_CONSTANT(bool, value = true);
- };
-
- } // namespace system
-} // namespace boost
-
-namespace cgi {
- namespace error {
-
- inline boost::system::error_code make_error_code(fcgi_errors e)
- {
- return boost::system::error_code(
- static_cast<int>(e), get_fcgi_category());
- }
-
   } // namespace error
 } // namespace cgi
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -18,7 +18,7 @@
    /// Typedef for common usage (FCGI)
    typedef
      ::cgi::common::basic_request_acceptor<
- fcgi_request_acceptor_service<>
+ fcgi_request_acceptor_service<>
>
    acceptor;
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor_service_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor_service_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/acceptor_service_impl.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -28,7 +28,7 @@
 #include "boost/cgi/fwd/basic_protocol_service_fwd.hpp"
 
 namespace cgi {
-
+
    namespace detail {
 
      /// Helper functions for async_accept operation.
@@ -54,7 +54,7 @@
        typename T::implementation_type::request_type& request;
        Handler handler;
      };
-
+
    } // namespace detail
 
   namespace fcgi {
@@ -81,7 +81,7 @@
 
      /// The unique service identifier
      //static boost::asio::io_service::id id;
-
+
      struct implementation_type
      {
        typedef Protocol_ protocol_type;
@@ -97,14 +97,14 @@
        typedef boost::asio::ip::tcp::endpoint endpoint_type;
        //typedef typename
        // acceptor_service_type::native_type native_type;
-
+
        acceptor_service_type::implementation_type acceptor_;
        boost::mutex mutex_;
        std::queue<boost::shared_ptr<request_type> > waiting_requests_;
        protocol_service_type* service_;
        port_number_type port_num_;
        endpoint_type endpoint_;
- };
+ };
 
      typedef acceptor_service_impl<Protocol_> type;
      typedef typename
@@ -122,9 +122,9 @@
      typedef typename
        acceptor_service_type::native_type native_type;
 
- typedef typename
+ typedef typename
        type::implementation_type::endpoint_type endpoint_type;
-
+
 
      explicit acceptor_service_impl(::cgi::common::io_service& ios)
        : detail::service_base< ::cgi::fcgi::acceptor_service_impl<Protocol_> >(ios)
@@ -132,7 +132,7 @@
        //, endpoint(boost::asio::ip::tcp::v4())
      {
      }
-
+
      protocol_service_type&
        service(implementation_type const& impl) const
      {
@@ -172,7 +172,7 @@
        impl.protocol_service_ = &ps;
      }
 
- protocol_service_type&
+ protocol_service_type&
        get_protocol_service(implementation_type& impl)
      {
        BOOST_ASSERT(impl.service_ != NULL);
@@ -184,25 +184,25 @@
        acceptor_service_.construct(impl.acceptor_);
        //impl.acceptor_ptr().reset(impl::acceptor_type(this->io_service()));
      }
-
+
      void destroy(implementation_type& impl)
      {
        // close/reject all the waiting requests
        /***/
        acceptor_service_.destroy(impl.acceptor_);
      }
-
+
      void shutdown_service()
      {
        acceptor_service_.shutdown_service();
      }
-
+
      /// Check if the given implementation is open.
      bool is_open(implementation_type& impl)
      {
        return acceptor_service_.is_open(impl.acceptor_);
      }
-
+
      /// Open a new *socket* acceptor implementation.
      boost::system::error_code
        open(implementation_type& impl, const native_protocol_type& protocol
@@ -210,7 +210,7 @@
      {
        return acceptor_service_.open(impl.acceptor_, protocol, ec);
      }
-
+
      template<typename Endpoint>
      boost::system::error_code
        bind(implementation_type& impl, const Endpoint& endpoint
@@ -220,7 +220,7 @@
            boost::asio::socket_base::reuse_address(true), ec);
        return acceptor_service_.bind(impl.acceptor_, endpoint, ec);
      }
-
+
      /// Assign an existing native acceptor to a *socket* acceptor.
      boost::system::error_code
        assign(implementation_type& impl, const native_protocol_type& protocol
@@ -229,14 +229,14 @@
      {
        return acceptor_service_.assign(impl.acceptor_, protocol
                                       , native_acceptor, ec);
- }
-
+ }
+
      boost::system::error_code
        listen(implementation_type& impl, int backlog, boost::system::error_code& ec)
      {
        return acceptor_service_.listen(impl.acceptor_, backlog, ec);
      }
-
+
      /// Accepts one request.
      template<typename CommonGatewayRequest>
      boost::system::error_code
@@ -275,7 +275,6 @@
        {
          request.clear();
        }
- //request.clear(); // **FIXME** (this should be cleverer)
 
        // If we can reuse this request's connection, return.
        if (request.client().keep_connection())
@@ -285,12 +284,11 @@
        return acceptor_service_.accept(impl.acceptor_,
                 request.client().connection()->next_layer(), endpoint, ec);
      }
-
+
      /// Asynchronously accepts one request.
- //template<typename CommonGatewayRequest, typename Handler>
- //void async_accept(implementation_type& impl, CommonGatewayRequest& request
      template<typename Handler>
- void async_accept(implementation_type& impl, typename implementation_type::request_type& request
+ void async_accept(implementation_type& impl
+ , typename implementation_type::request_type& request
                       , Handler handler)
      {
        this->io_service().post(
@@ -330,7 +328,7 @@
        return false;
 #endif
      }
-
+
    public:
      template<typename CommonGatewayRequest, typename Handler>
      void check_for_waiting_request(implementation_type& impl
@@ -356,16 +354,15 @@
        return acceptor_service_.async_accept(impl.acceptor_,
          request.client().connection()->next_layer(), 0, handler);
      }
-
+
    public:
      /// The underlying socket acceptor service.
      acceptor_service_type& acceptor_service_;
    };
-
+
  } // namespace fcgi
 } // namespace cgi
-
+
 #include "boost/cgi/detail/pop_options.hpp"
 
 #endif // CGI_FCGI_ACCEPTOR_SERVICE_IMPL_HPP_INCLUDED__
-

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -281,6 +281,11 @@
       return bytes_left_;
     }
 
+ boost::uint16_t const& request_id() const
+ {
+ return request_id_;
+ }
+
   public:
     friend class fcgi_request_service;
     boost::uint16_t request_id_;

Added: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/error.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,133 @@
+// -- error.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)
+//
+// Abstract:
+// ---------
+//
+// The errors for everything are defined in here. ie. FastCGI,
+// CGI and SCGI errors.
+//
+// **FIXME** This is a mess.
+//
+////////////////////////////////////////////////////////////////
+#ifndef BOOST_FCGI_ERROR_HPP_INCLUDED__
+#define BOOST_FCGI_ERROR_HPP_INCLUDED__
+
+#include <string>
+#include <boost/system/error_code.hpp>
+
+namespace cgi {
+ namespace error {
+
+enum fcgi_errors
+{
+ bad_header_type = 1,
+
+ /// A packet arrived for a request id that doesn't exist and the packet
+ // wasn't a BEGIN_REQUEST record.
+ bad_request_id,
+
+ /// When trying to write a packet, the client::write_some() call didn't
+ // transmit enough data before returning.
+ couldnt_write_complete_packet,
+
+ // Tried to read/write from/to the client associated to a request when it
+ // was closed.
+ client_closed,
+
+ // Self-explanatory (not much a user can do about this though).
+ abort_request_record_recieved_for_invalid_request,
+
+ // For now a user has to recognise this error and construct a request
+ // themselves. This is an ugly hack.
+ multiplexed_request_incoming,
+
+ // A begin_request packet has come in with an existing request id.
+ duplicate_request,
+
+ // Calling async_accept on a request that hasn't been closed isn't
+ // allowed.
+ accepting_on_an_open_request,
+
+ invalid_socket,
+
+ // The CONTENT_TYPE for form data wasn't recognised.
+ invalid_form_type,
+
+ // Used in basic_connection<tags::stdio>
+ // **FIXME**
+ broken_pipe,
+
+ // **FIXME**
+ bad_read,
+
+ // A client wasn't able to open.
+ client_not_open
+};
+
+ namespace detail {
+
+class fcgi_category
+ : public boost::system::error_category
+{
+public:
+ const char* name() const { return "fcgi_error"; }
+ std::string message(int e) const
+ {
+ switch(e)
+ {
+ case client_closed:
+ return "You are trying to read from or write to a closed client.";
+ case multiplexed_request_incoming:
+ return "A new request is pending on this connection (ie. it is "
+ "multiplexed). This isn't handled for now. **FIXME**";
+ case accepting_on_an_open_request:
+ return "You called async_accept before closing a request.";
+ default:
+ return "(FastCGI) BOOM!!!";
+ }
+ }
+};
+
+ } // namespace detail
+
+inline const boost::system::error_category& get_fcgi_category()
+{
+ static detail::fcgi_category instance;
+ return instance;
+}
+
+static const boost::system::error_category& fcgi_category
+ = ::cgi::error::get_fcgi_category();
+
+ } // namespace error
+} // namespace cgi
+
+namespace boost {
+ namespace system {
+
+ template<> struct is_error_code_enum< ::cgi::error::fcgi_errors>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+
+ } // namespace system
+} // namespace boost
+
+namespace cgi {
+ namespace error {
+
+ inline boost::system::error_code make_error_code(fcgi_errors e)
+ {
+ return boost::system::error_code(
+ static_cast<int>(e), get_fcgi_category());
+ }
+
+ } // namespace error
+} // namespace cgi
+
+#endif // BOOST_FCGI_ERROR_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/request_service.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -174,14 +174,15 @@
      * packet for this request arrives from the server.
      *
      */
+
     boost::system::error_code
     load(implementation_type& impl, bool parse_stdin
           , boost::system::error_code& ec);
-
+/*
     boost::system::error_code
     load(implementation_type& impl, common::parse_options parse_opts
           , boost::system::error_code& ec);
-
+*/
     // **FIXME**
     template<typename Handler>
     void async_load(implementation_type& impl, bool parse_stdin, Handler handler);

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/fcgi_request_service.ipp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -161,7 +161,7 @@
 
       return ec;
     }
-*/
+/*/
     BOOST_CGI_INLINE boost::system::error_code
     fcgi_request_service::load(
         implementation_type& impl, bool parse_stdin
@@ -171,7 +171,9 @@
       BOOST_ASSERT(!ec && "Can't load request due to previous errors.");
 
       impl.client_.construct(impl, ec);
- BOOST_ASSERT(impl.client_.connection_->is_open());
+ // Bomb out if the client isn't open here.
+ if (!impl.client_.connection_->is_open())
+ return error::client_not_open;
 
       for(;;)
       {
@@ -236,6 +238,7 @@
       );
     }
 
+ /// Check if the params have been read (ie. FCGI_PARAMS packets)
     BOOST_CGI_INLINE
     bool fcgi_request_service::params_read(implementation_type& impl)
     {

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/form_parser.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/form_parser.ipp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/form_parser.ipp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -15,6 +15,8 @@
 #include "boost/cgi/common/form_parser.hpp"
 #include "boost/cgi/common/source_enums.hpp"
 
+#include <iostream> // **FIXME**
+
 namespace cgi {
  namespace detail {
 
@@ -115,7 +117,7 @@
               str.append(1, detail::hex_to_char(ch, ch1));
             }
             else // we don't have a hex sequence
- {
+ { // **FIXME** isn't this broken? What about '%%53' ? - use url_decode instead!
               str.append(1, '%').append(1, ch).append(1, ch1);
             }
             bytes_left_ -= 2;
@@ -459,6 +461,7 @@
     {
       //BOOST_ASSERT(!content_type.empty());
 
+ // **FIXME** (don't use Boost.Regex)
       boost::regex re("; ?boundary=\"?([^\"\n\r]+)\"?");
       boost::smatch match_results;
       if (!boost::regex_search(content_type_, match_results, re))

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/impl/response.ipp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -324,6 +324,23 @@
   }
 
   template<typename T> BOOST_CGI_INLINE
+ typename basic_response<T>::string_type
+ basic_response<T>::header_value(string_type const& name)
+ {
+ for(std::vector<std::string>::iterator iter = headers_.begin(), end = headers_.end();
+ iter != end; ++iter)
+ {
+ if (iter->substr(0,name.length()) == name)
+ {
+ // Extract the value (assumes there's at most one space after the separator.
+ int start(name.length() + (iter->at(name.length()+1) == ' ' ? 2 : 1));
+ return iter->substr(start, iter->length()-start-2); // strip the trailing \r\n
+ }
+ }
+ return headers_.back();
+ }
+
+ template<typename T> BOOST_CGI_INLINE
   void basic_response<T>::clear_headers()
     {
       BOOST_ASSERT(!headers_terminated_);
@@ -343,18 +360,23 @@
       return headers_terminated_;
     }
 
- // Is this really necessary?
+ // Is this really necessary?
   template<typename T> BOOST_CGI_INLINE
   void basic_response<T>::end_headers()
   {
     headers_terminated_ = true;
   }
 
- /// Get the ostream containing the response body.
+ /// Get the ostream containing the response body.
   template<typename T> BOOST_CGI_INLINE
   typename basic_response<T>::ostream_type&
     basic_response<T>::ostream() { return ostream_; }
     
+ /// Get the ostream containing the response body.
+ template<typename T> BOOST_CGI_INLINE
+ std::vector<typename basic_response<T>::string_type>&
+ basic_response<T>::headers() { return headers_; }
+
   // Send the response headers and mark that they've been sent.
   template<typename T>
   template<typename ConstBufferSequence> BOOST_CGI_INLINE
@@ -435,14 +457,14 @@
    */
   template<typename T> BOOST_CGI_INLINE
   cgi::common::basic_response<T>&
- operator<< (cgi::common::basic_response<T> const& resp
+ operator<< (cgi::common::basic_response<T>& resp
                , cgi::common::basic_cookie<T> ck)
   {
     BOOST_ASSERT(!resp.headers_terminated());
     resp.set_header("Set-cookie", ck.to_string());
     return resp;
   }
-
+/*
   template<typename T> BOOST_CGI_INLINE
   cgi::common::basic_response<T>&
     operator<< (cgi::common::basic_response<T>& resp
@@ -452,7 +474,7 @@
     resp.set_header("Set-cookie", ck.to_string());
     return resp;
   }
-
+*/
   template<typename T> BOOST_CGI_INLINE
   cgi::common::basic_response<T>&
     operator<< (cgi::common::basic_response<T>& resp
@@ -462,6 +484,23 @@
     return resp.set_status(status);
   }
 
+ template<typename charT> BOOST_CGI_INLINE
+ cgi::common::basic_response<charT>&
+ operator<< (cgi::common::basic_response<charT>& resp
+ , cgi::common::basic_response<charT>& other_resp)
+ {
+ BOOST_ASSERT(!resp.headers_terminated());
+ for(std::vector<std::string>::iterator iter = other_resp.headers().begin(), end = other_resp.headers().end();
+ iter != end; ++iter)
+ {
+ if (iter->substr(0,13) != "Content-type:") // Don't overwrite the content-type.
+ resp.headers().push_back(*iter);
+ }
+ resp.ostream()<< other_resp.ostream().rdbuf();
+ return resp;
+ }
+
+
 #undef BOOST_CGI_ADD_DEFAULT_HEADER
 
 #include "boost/cgi/detail/pop_options.hpp"

Added: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,18 @@
+// -- utility.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)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_UTILITY_HPP_INCLUDED__
+#define CGI_UTILITY_HPP_INCLUDED__
+
+// #include all utility headers.
+#include "boost/cgi/utility/has_key.hpp"
+#include "boost/cgi/utility/redirect.hpp"
+//#include "boost/cgi/utility/get_value.hpp"
+//#include "boost/cgi/utility/get_as.hpp"
+
+#endif // CGI_UTILITY_HPP_INCLUDED__

Added: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/get_value.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/get_value.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,49 @@
+
+#ifndef BOOST_CGI_REDIRECT_HPP_INCLUDED_
+#define BOOST_CGI_REDIRECT_HPP_INCLUDED_
+
+#include <string>
+///////////////////////////////////////////////////////////
+#include <boost/system/error_code.hpp>
+///////////////////////////////////////////////////////////
+#include "boost/cgi/import/write.hpp"
+#include "boost/cgi/common/header.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+
+namespace cgi {
+ namespace common {
+
+ /// Redirect a request to another place.
+ /**
+ * Note that without also outputting a content-type header, this will be a
+ * 'soft' redirect and the location won't be updated. If you want to do a
+ * 'hard' redirect, pass a 'Content-type: text/plain' header along with
+ * two CRLFs to complete the headers.
+ */
+ template <typename RequestT>
+ basic_header<typename RequestT::char_type>
+ redirect(RequestT& req, typename RequestT::string_type const& dest
+ , bool secure, boost::system::error_code& ec)
+ {
+ std::string url(secure ? "https" : "http");
+ url += "://" + req.server_name() + "/" + dest;
+ basic_header<typename RequestT::char_type> hdr("Location", url);
+ return hdr;
+ }
+
+ template <typename RequestT>
+ basic_header<typename RequestT::char_type>
+ redirect(RequestT& req, typename RequestT::string_type const& dest, bool secure = false)
+ {
+ boost::system::error_code ec;
+ basic_header<typename RequestT::char_type>
+ hdr(redirect(req, dest, secure, ec));
+ detail::throw_error(ec);
+ return hdr;
+ }
+
+ } // namespace common
+} // namespace cgi
+
+#endif // BOOST_CGI_REDIRECT_HPP_INCLUDED_
+

Added: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/has_key.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/has_key.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,59 @@
+
+#ifndef BOOST_CGI_HAS_KEY_HPP_INCLUDED_
+#define BOOST_CGI_HAS_KEY_HPP_INCLUDED_
+
+#include <map>
+///////////////////////////////////////////////////////////
+#include "boost/cgi/common/name.hpp"
+
+namespace cgi {
+ namespace common {
+
+ /// Check if the given map has an entry `name`.
+ /**
+ * Examples:
+ *
+ * Take a map who's keys are case insensitive:
+ *
+ * std::map<common::name,std::string> icase_map;
+ * icase_map["key1"] = "value1";
+ * icase_map["key2"] = "value2";
+ * has_key(icase_map, "key1"); // true
+ * has_key(icase_map, "KEY1"); // true
+ * has_key(icase_map, "key2"); // true
+ * has_key(icase_map, "key3"); // false
+ *
+ * CGI data is also held in maps with case-insensitive keys.
+ * If you sent a request that looked something like, which made its way to
+ * your CGI app (probably after being received by your HTTP server):
+ *
+ * GET some_cgi_script?foo=bar HTTP/1.1
+ *
+ * If you wrote `some_cgi_script` and initialised a request, `req`, then:
+ *
+ * has_key(req[env], "script_name") // true
+ * has_key(req[env], "SCRIPT_NAME") // true
+ * has_key(req[get], "blah") // false
+ * has_key(req[form], "foo") // true
+ *
+ * Note that the last line above would also be matched by a POST request,
+ * with the same data `foo=bar`.
+ */
+ template<typename MapT>
+ bool has_key(MapT& data, common::name const& name)
+ {
+ if (!data.empty())
+ for(MapT::const_iterator iter = data.begin(), end = data.end();
+ iter != end; ++iter)
+ {
+ if (iter->first == name)
+ return true;
+ }
+ return false;
+ }
+
+ } // namespace common
+} // namespace cgi
+
+#endif // BOOST_CGI_HAS_KEY_HPP_INCLUDED_
+

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/redirect.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/redirect.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/utility/redirect.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -6,30 +6,40 @@
 ///////////////////////////////////////////////////////////
 #include <boost/system/error_code.hpp>
 ///////////////////////////////////////////////////////////
-#include "boost/cgi/write.hpp"
-#include "boost/cgi/header.hpp"
+#include "boost/cgi/import/write.hpp"
+#include "boost/cgi/common/header.hpp"
 #include "boost/cgi/detail/throw_error.hpp"
 
 namespace cgi {
  namespace common {
 
    /// Redirect a request to another place.
+ /**
+ * Note that without also outputting a content-type header, this will be a
+ * 'soft' redirect and the location won't be updated. If you want to do a
+ * 'hard' redirect, pass a 'Content-type: text/plain' header along with
+ * two CRLFs to complete the headers.
+ */
    template <typename RequestT>
- boost::system::error_code
+ basic_header<typename RequestT::char_type>
    redirect(RequestT& req, typename RequestT::string_type const& dest
- , boost::system::error_code& ec)
+ , bool secure, boost::system::error_code& ec)
    {
- basic_header<typename RequestT::char_type> hdr("Location", dest);
- write(req.client(), buffer(hdr.content), ec);
- return ec;
+ std::string url(secure ? "https" : "http");
+ url += "://" + req.server_name() + "/" + dest;
+ basic_header<typename RequestT::char_type> hdr("Location", url);
+ return hdr;
    }
 
    template <typename RequestT>
- void redirect(RequestT& req, std::string const& dest)
+ basic_header<typename RequestT::char_type>
+ redirect(RequestT& req, typename RequestT::string_type const& dest, bool secure = false)
    {
      boost::system::error_code ec;
- redirect(req, dest, ec);
+ basic_header<typename RequestT::char_type>
+ hdr(redirect(req, dest, secure, ec));
      detail::throw_error(ec);
+ return hdr;
    }
 
  } // namespace common

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Amortization/Amortization.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Amortization/Amortization.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.ncb
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.sln
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.suo
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_cookie_game/acgi_cookie_game.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_cookie_game/acgi_cookie_game.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_echo/acgi_echo.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_echo/acgi_echo.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/acgi_hello_world/acgi_hello_world.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_ctemplate_debug_server/cgi_ctemplate_debug_server.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_ctemplate_debug_server/cgi_ctemplate_debug_server.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_debug_server/cgi_debug_server.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_debug_server/cgi_debug_server.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_echo/cgi_echo.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_echo/cgi_echo.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_hello_world/cgi_hello_world.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/cgi_hello_world/cgi_hello_world.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_hello_world/fcgi_hello_world.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_hello_world/fcgi_hello_world.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/xcgi_server1/xcgi_server1.vcproj
==============================================================================
Binary file. No diff available.

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/xcgi_server1/xcgi_server1.vcproj.360-SYSTEMS.darreng.user
==============================================================================
Binary file. No diff available.

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/doc/src/user_guide/tutorial/quickstart.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/doc/src/user_guide/tutorial/quickstart.qbk (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/doc/src/user_guide/tutorial/quickstart.qbk 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -7,7 +7,21 @@
 
 [section:quickstart Quickstart: 'Scripting']
 
-CGI is a simple protocol: you read __POST__ data from `stdin`, other data from environment variables (ie. via [@http://tinyurl.com/3cqrd5 `::getenv()`]) and write your output to `stdout`. This section introduces the '__CGI__' interface, which offers a subset of the library's functionality. This is not essential reading, but it is recommended that you at least scan through it as the techniques still apply to the rest of the library. Afterwards, if you wish to scale your program to __FastCGI__ or __SCGI__, or just provide a custom logging layer or asynchronous read/writes (with vanilla CGI) then the rest of the tutorial will show you how to.
+CGI
+is
+a
+simple
+protocol:
+you
+read
+__POST__
+data
+from
+`stdin`,
+other
+data
+from
+environment variables (ie. via [@http://tinyurl.com/3cqrd5 `::getenv()`]) and write your output to `stdout`. This section introduces the '__CGI__' interface, which offers a subset of the library's functionality. This is not essential reading, but it is recommended that you at least scan through it as the techniques still apply to the rest of the library. Afterwards, if you wish to scale your program to __FastCGI__ or __SCGI__, or just provide a custom logging layer or asynchronous read/writes (with vanilla CGI) then the rest of the tutorial will show you how to.
 
 [h3 10 minute intro]
 
@@ -17,6 +31,11 @@
 
 [main]
 
-That's all quite simple, right?
+[section:building Building]
+
+Now to compile and run the example. It's probably beyond the scope of these docs to go into too
+much detail here but
+
+[endsect]
 
 [endsect]

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/acgi_amort.html
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/acgi_amort.html 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,179 @@
+<html>
+<head>
+ <link rel="stylesheet" type="text/css" href="/css/acgi_amort.css">
+
+ <title>Fixed Mortgage Loan Calculator</title>
+ <script type="text/javascript" language="JavaScript1.2" src="/js/acgi_amort.js"></script>
+</head>
+
+<body>
+
+{{!--Amortization form}}
+<form name="AmortBrowser" action="{{SCRIPT_NAME}}" method="post">
+ <input type="hidden" name="Amortize" value="1">
+ <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
+ <tr>
+ <td colspan=4 class=tblhead align=center>FIXED MORTGAGE LOAN CALCULATOR</td>
+ </tr>
+ <tr>
+ <td colspan=2 class=tblhead align=center>Loan Information</td>
+ <td colspan=2 class=tblhead align=center>Prepayment Information (optional)</td>
+ </tr>
+ <tr>
+ <td width="250" class="td1">Mortgage Amount</td>
+ <td class="td2">
+ <input name="LoanAmt" type="text" onBlur="this.value=formatCurrency(this.value);" value="{{LoanAmt}}" size="10">
+ </td>
+ <td width="250" class="td1">Prepayment Frequency</td>
+ <td class="td2">
+ <select name="PrePmtFreq">
+ <option value="weekly"{{PrePmtFreq_weekly}}>Weekly</option>
+ <option value="monthly"{{PrePmtFreq_monthly}}>Monthly</option>
+ <option value="halfyearly"{{PrePmtFreq_halfyearly}}>Half-yearly</option>
+ <option value="yearly"{{PrePmtFreq_yearly}}>Yearly</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="td1">Interest (APR)</td>
+ <td class="td2">
+ <input name="YearlyIntRate" type="text" value="{{YearlyIntRate}}" size="10">
+ </td>
+ <td class="td1">Prepayment Amount</td>
+ <td class="td2">
+ <input name="PrePmtAmt" type="text" value="{{PrePmtAmt}}" size="17" {{PrePmtFreqInvalid}}>
+ </td>
+ </tr>
+ <tr>
+ {{!-- Length of Loan selection list }}
+ <td class="td1">Length of Loan</td>
+ <td class="td2">
+ <select name="TermYrs">
+ {{#SELECT_TERM_YEARS}}
+ <option value="{{TermYrs}}">{{TermYrs}} Years</option>
+ {{/SELECT_TERM_YEARS}}
+ </select>
+ </td>
+ <td class="td1">Start with Payment</td>
+ <td class="td2">
+ <input name="PrePmtBegin" type="text" value="{{PrePmtBegin}}" size="17">
+ </td>
+ </tr>
+ <tr>
+ <td class="td1"></td>
+ <td class="td2">
+ <input type="submit" value="Calculate">
+ </td>
+ </tr>
+
+ {{#NotAmortize}}
+ <tr>
+ <td colspan="4" class="td2"><span class="small">
+ DISCLAIMER: The figures above are based upon conventional program guidelines.<br>
+ Calculations by this tool are believed to be accurate, yet are not guaranteed. Further review is<br>
+ necessary to obtain an exact qualification. If you have less than 20% equity in your home, a monthly<br>
+ mortgage insurance payment may be required.
+ </span></td>
+ </tr>
+ {{/NotAmortize}}
+
+ </table>
+</form>
+
+{{!--Prepayment summary table}}
+{{#PrePmtSummary}}
+ <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
+ <tr>
+ <td colspan=4 class=tblhead align=center>PREPAYMENT vs REGULAR PAYMENT</td>
+ </tr>
+ <tr>
+ <td colspan=2 class=tblhead align=center>Prepayment Results</td>
+ <td colspan=2 class=tblhead align=center>Regular Payment Results</td>
+ </tr>
+ <tr>
+ <td class="td1">Number of months to pay loan</td>
+ <td class="td2" width="125">
+ <center><b>{{PrePmt_iPmtNo}}</b></center>
+ </td>
+ <td class="td1"></td>
+ <td class="td2" width="125">
+ <center><b>{{RegPmt_iPmtNo}}</b></center>
+ </td>
+ </tr>
+ <tr>
+ <td class="td1">Total Interest Paid</td>
+ <td class="td2" align="right">{{PrePmt_TotalIntPd}}</td>
+ <td class="td1"></td>
+ <td class="td2" align="right">{{RegPmt_TotalIntPd}}</td>
+ </tr>
+ <tr>
+ <td width="250" class="td1">Total Payments</td>
+ <td class="td2" align="right">{{PrePmt_TotalPmts}}</td>
+ <td width="250" class="td1"></td>
+ <td class="td2" align="right">{{RegPmt_TotalPmts}}</td>
+ </tr>
+ <tr>
+ <td colspan="4" class="td2"><span class="small">
+ <br>
+ By applying the prepayments in the schedule above, you would <u>realize these savings</u>:
+ <ul>
+ <li>
+ You pay the <b>{{RegPmt_term_to_words}}</b> loan in <b>{{PrePmt_term_to_words}}</b>
+ <br><br>
+ <li>The total loan payments will be <b>{{PrePmt_TotalPmts}}</b> instead of <b>{{RegPmt_TotalPmts}}</b>
+ </ul>
+ </span></td>
+ </tr>
+ </table>
+ <br>
+{{/PrePmtSummary}}
+
+{{#RegPmtSummary}}
+ {{!--Regular Payment summary table}}
+ <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
+ <tr>
+ <td colspan=4 class=tblhead align=center>REGULAR PAYMENT SUMMARY</td>
+ </tr>
+ <tr>
+ <td class="td1">Monthly Payment</td>
+ <td class="td2" width="125" align="right"><b>£{{MonthlyPmt}}</b></td>
+ </tr>
+ <tr>
+ <td class="td1">Total Interest Paid</td>
+ <td class="td2" width="125" align="right">£{{RegPmt_TotalIntPd}}</td>
+ </tr>
+ <tr>
+ <td class="td1">Total Payments</td>
+ <td class="td2" width="125" align="right">£{{RegPmt_TotalPmts}}</td>
+ </tr>
+ </table>
+ <br>
+{{/RegPmtSummary}}
+
+{{!--Amortization table}}
+
+{{#Amortize}}
+ <table border=0 cellpadding=0 cellspacing=1 width=550 class="tblbase">
+ <tr>
+ <td colspan=6 class=tblhead align=center>AMORTIZATION TABLE</td>
+ </tr>
+ <td class=tblhead align=center>Payment</td>
+ <td class=tblhead align=center>Mo. Payment</td>
+ <td class=tblhead align=center>Interest Pd.</td>
+ <td class=tblhead align=center>Principal Pd.</td>
+ <td class=tblhead align=center>New Balance</td>
+ {{#PaymentEntry}}
+ <tr class=row{{ROW_TYPE}}>
+ <td ALIGN=CENTER>{{ROW_NUM}}</td>
+ <td>£{{Payment}}</td>
+ <td>£{{InterestPaid}}</td>
+ <td>£{{PrincipalPaid}}</td>
+ <td>£{{Balance}}</td>
+ </tr>
+ {{/PaymentEntry}}
+ </table>
+{{/Amortize}}
+
+</body>
+</html>
+

Deleted: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/acgi_amort.tpl
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/acgi_amort.tpl 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
+++ (empty file)
@@ -1,174 +0,0 @@
-<html>
-<head>
- <link rel="stylesheet" type="text/css" href="/acgi_amort.css">
-
- <title>Fixed Mortgage Loan Calculator</title>
- <script type="text/javascript" language="JavaScript1.2" src="/acgi_amort.js"></script>
-</head>
-
-<body>
-
-{{!--Amortization form}}
-<form name="AmortBrowser" action="acgi_amort" method="post">
- <input type="hidden" name="Amortize" value="1">
- <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
- <tr>
- <td colspan=4 class=tblhead align=center>FIXED MORTGAGE LOAN CALCULATOR</td>
- </tr>
- <tr>
- <td colspan=2 class=tblhead align=center>Loan Information</td>
- <td colspan=2 class=tblhead align=center>Prepayment Information (optional)</td>
- </tr>
- <tr>
- <td width="250" class="td1">Mortgage Amount</td>
- <td class="td2">
- <input name="LoanAmt" type="text" onBlur="this.value=formatCurrency(this.value);" value="{{LoanAmt}}" size="10">
- </td>
- <td width="250" class="td1">Prepayment Frequency</td>
- <td class="td2">
- <select name="PrePmtFreq" {{PrePmtFreqInvalid}}>{{PrePmtFreq}}</select>
- </td>
- </tr>
- <tr>
- <td class="td1">Interest (APR)</td>
- <td class="td2">
- <input name="YearlyIntRate" type="text" value="{{YearlyIntRate}}" size="10">
- </td>
- <td class="td1">Prepayment Amount</td>
- <td class="td2">
- <input name="PrePmtAmt" type="text" value="{{PrePmtAmt}}" size="17" {{PrePmtFreqInvalid}}>
- </td>
- </tr>
- <tr>
- {{!-- Length of Loan selection list }}
- <td class="td1">Length of Loan</td>
- <td class="td2">
- <select name="TermYrs">
- {{#SELECT_TERM_YEARS}}
- <option value="{{TermYrs}}">{{TermYrs}} Years</option>
- {{/SELECT_TERM_YEARS}}
- </select>
- </td>
- <td class="td1">Start with Payment</td>
- <td class="td2">
- <input name="PrePmtBegin" type="text" value="{{PrePmtBegin}}" size="17">
- </td>
- </tr>
- <tr>
- <td class="td1"></td>
- <td class="td2">
- <input type="submit" value="Calculate">
- </td>
- </tr>
-
- {{#NotAmortize}}
- <tr>
- <td colspan="4" class="td2"><span class="small">
- DISCLAIMER: The figures above are based upon conventional program guidelines.<br>
- Calculations by this tool are believed to be accurate, yet are not guaranteed. Further review is<br>
- necessary to obtain an exact qualification. If you have less than 20% equity in your home, a monthly<br>
- mortgage insurance payment may be required.
- </span></td>
- </tr>
- {{/NotAmortize}}
-
- </table>
-</FORM>
-
-{{!--Prepayment summary table}}
-{{#PrePmtSummary}}
- <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
- <tr>
- <td colspan=4 class=tblhead align=center>PREPAYMENT vs REGULAR PAYMENT</td>
- </tr>
- <tr>
- <td colspan=2 class=tblhead align=center>Prepayment Results</td>
- <td colspan=2 class=tblhead align=center>Regular Payment Results</td>
- </tr>
- <tr>
- <td class="td1">Number of months to pay loan</td>
- <td class="td2" width="125">
- <center><b>{{PrePmt_iPmtNo}}</b></center>
- </td>
- <td class="td1"></td>
- <td class="td2" width="125">
- <center><b>{{RegPmt_iPmtNo}}</b></center>
- </td>
- </tr>
- <tr>
- <td class="td1">Total Interest Paid</td>
- <td class="td2" align="right">{{PrePmt_TotalIntPd}}</td>
- <td class="td1"></td>
- <td class="td2" align="right">{{RegPmt_TotalIntPd}}</td>
- </tr>
- <tr>
- <td width="250" class="td1">Total Payments</td>
- <td class="td2" align="right">{{PrePmt_TotalPmts}}</td>
- <td width="250" class="td1"></td>
- <td class="td2" align="right">{{RegPmt_TotalPmts}}</td>
- </tr>
- <tr>
- <td colspan="4" class="td2"><span class="small">
- <br>
- By applying the prepayments in the schedule above, you would <u>realize these savings</u>:
- <ul>
- <li>
- You pay the <b>{{RegPmt_term_to_words}}</b> loan in <b>{{PrePmt_term_to_words}}</b>
- <br><br>
- <li>The total loan payments will be <b>{{PrePmt_TotalPmts}}</b> instead of <b>{{RegPmt_TotalPmts}}</b>
- </ul>
- </span></td>
- </tr>
- </table>
- <br>
-{{/PrePmtSummary}}
-
-{{#RegPmtSummary}}
- {{!--Regular Payment summary table}}
- <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
- <tr>
- <td colspan=4 class=tblhead align=center>REGULAR PAYMENT SUMMARY</td>
- </tr>
- <tr>
- <td class="td1">Monthly Payment</td>
- <td class="td2" width="125" align="right"><b>${{MonthlyPmt}}</b></td>
- </tr>
- <tr>
- <td class="td1">Total Interest Paid</td>
- <td class="td2" width="125" align="right">${{RegPmt_TotalIntPd}}</td>
- </tr>
- <tr>
- <td class="td1">Total Payments</td>
- <td class="td2" width="125" align="right">${{RegPmt_TotalPmts}}</td>
- </tr>
- </table>
- <br>
-{{/RegPmtSummary}}
-
-{{!--Amortization table}}
-
-{{#Amortize}}
- <table border=0 cellpadding=0 cellspacing=1 width=550 class="tblbase">
- <tr>
- <td colspan=6 class=tblhead align=center>AMORTIZATION TABLE</td>
- </tr>
- <td class=tblhead align=center>Payment</td>
- <td class=tblhead align=center>Mo. Payment</td>
- <td class=tblhead align=center>Interest Pd.</td>
- <td class=tblhead align=center>Principal Pd.</td>
- <td class=tblhead align=center>New Balance</td>
- {{#PaymentEntry}}
- <tr class=row{{ROW_TYPE}}>
- <td ALIGN=CENTER>{{ROW_NUM}}</td>
- <td>${{Payment}}</td>
- <td>${{InterestPaid}}</td>
- <td>${{PrincipalPaid}}</td>
- <td>${{Balance}}</td>
- </tr>
- {{/PaymentEntry}}
- </table>
-{{/Amortize}}
-
-</body>
-</html>
-

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/amortization/main.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -21,6 +21,7 @@
 #include <iostream>
 #include <iomanip>
 #include <boost/cgi/acgi.hpp>
+#include <boost/cgi/utility.hpp>
 #include <boost/algorithm/string/regex.hpp>
 #include <google/template.h>
 
@@ -30,19 +31,31 @@
 std::string string_from_currency(std::string amt)
 {
   // this is much too hardcore, but it works fine...
- boost::algorithm::erase_all_regex(amt, boost::regex("[$, ]"));
+ boost::algorithm::erase_all_regex(amt, boost::regex("[£$, ]"));
   return amt;
 }
 
+template<typename Request, typename Dictionary>
+void get_prepayment_frequency(Request& req, Dictionary& dict)
+{
+ std::string val(has_key(req[form], "PrePmtFreq")
+ ? req[form]["PrePmtFreq"]
+ : "Monthly");
+ dict.SetValue("PrePmtFreq_" + val, " selected=\"selected\"");
+}
+
 /// This function fills the dictionary and sub-dictionaries with relevant values.
 template<typename Request>
 void fill_amortization_dictionary(google::TemplateDictionary& dict, Request& req)
 {
- std::string tmp( req[post]["LoanAmt"] );
- dict.SetValue("LoanAmt", tmp.empty() ? "$250,000" : tmp);
-
- tmp = req[post]["YearlyIntRate"];
- dict.SetValue("YearlyIntRate", tmp.empty() ? "6.000" : tmp);
+ dict.SetValue("SCRIPT_NAME", req.script_name());
+ dict.SetValue("LoanAmt", has_key(req[form],"LoadAmt")
+ ? req[form]["LoanAmt"]
+ : "£250,000");
+
+ dict.SetValue("YearlyIntRate", has_key(req[form],"YearlyIntRate")
+ ? req[form]["YearlyIntRate"]
+ : "6.000");
 
   boost::array<std::string, 8> year_opts
     = {{ "5", "7", "10", "20", "30", "40", "50" }};
@@ -51,14 +64,16 @@
   {
     dict.SetValueAndShowSection("TermYrs", year, "SELECT_TERM_YEARS");
   }
+
+ get_prepayment_frequency(req, dict);
 
- if (req[post]["Amortize"].empty())
+ if ( ! has_key(req[form], "Amortize") )
     dict.ShowSection("NotAmortize");
   else
   {
- double P = boost::lexical_cast<double>(string_from_currency(req[post]["LoanAmt"]));
- double i = boost::lexical_cast<double>(req[post]["YearlyIntRate"]) / 1200;
- double n = boost::lexical_cast<double>(req[post]["TermYrs"]) * 12;
+ double P = boost::lexical_cast<double>(string_from_currency(req[form]["LoanAmt"]));
+ double i = boost::lexical_cast<double>(req[form]["YearlyIntRate"]) / 1200;
+ double n = boost::lexical_cast<double>(req[form]["TermYrs"]) * 12;
     double monthly_payments = (P*i) / (1 - std::pow((1+i), -n));
     
     google::TemplateDictionary* sub_dict = dict.AddSectionDictionary("RegPmtSummary");
@@ -67,11 +82,11 @@
 
     dict.ShowSection("Amortize");
 
- double balance = P;
- int row_num = 0;
- double interest;
- double principal_paid;
- double total_interest;
+ double balance (P);
+ int row_num (0);
+ double interest (0);
+ double principal_paid (0);
+ double total_interest (0);
     do{
       google::TemplateDictionary* sub_dict2 = dict.AddSectionDictionary("PaymentEntry");
       sub_dict2->ShowSection("PaymentEntry");
@@ -101,11 +116,11 @@
   fill_amortization_dictionary(dict, req);
 
   google::Template* tmpl
- = google::Template::GetTemplate("example.tpl", google::STRIP_WHITESPACE);
+ = google::Template::GetTemplate("../templates/acgi_amort.html", google::STRIP_WHITESPACE);
 
   std::string arg(req[get]["arg"]);
   if (arg.empty())
- arg = "4"; // Make this the default
+ arg = "2"; // Make this the default
 
   // Depending on the value of `arg`, we can write the output in
   // different ways.
@@ -145,7 +160,7 @@
   if (arg == "4")
   {
     // Write the output directly to the request's client.
- std::string headers("Content-type: text/html\r\n\r\n");
+ std::string headers ("Content-type: text/html\r\n\r\n");
     write(req.client(), buffer(headers));
     std::string output;
     tmpl->Expand(&output, &dict);
@@ -170,15 +185,32 @@
   try{
     service s;
     request req(s);
- req.load(true);
+ req.load(parse_all);
     response resp;
 
     write_amortization_template(req, resp);
   
     return_(resp, req, 0);
+ }catch(boost::system::system_error* err){
+ std::cout<< "Content-type: text/plain\r\n\r\n"
+ << "Error (" << err->code() << "): " << err->what();
+ return 0;
+ }catch(boost::system::system_error& err){
+ std::cout<< "Content-type: text/plain\r\n\r\n"
+ << "Error (" << err.code() << "): " << err.what();
+ return 0;
+ }catch(std::exception* e){
+ std::cout<< "Content-type: text/html\r\n\r\n"
+ << "Exception caught: " << e->what();
+ return 0;
+ }catch(std::exception& e){
+ std::cout<< "Content-type: text/html\r\n\r\n"
+ << "Exception caught: " << e.what();
+ return 0;
   }catch(...){
     std::cout<< "Content-type: text/html\r\n\r\n"
- << "ERROR!! BOOM!";
+ << "Unknown error!";
+ return 0;
   }
 }
 //]

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/cookie_game/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/cookie_game/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/cookie_game/main.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -1,34 +1,154 @@
 #include <boost/cgi/acgi.hpp>
+#include <boost/cgi/utility.hpp>
 
-#define SCRIPT_NAME "acgi_cookie_game"
-
-//
-// ISSUES:
-// Currently won't work sometimes because the request data checks aren't case-insensitive,
-// like they should be.
-//
-
-// class handler
-// {
-// public:
-// handler(cgi::response& resp, boost::acgi::request& req)
-// : resp_(resp)
-// , req_(req)
-// {
-// }
-//
-// void operator()(boost::system::error_code& ec)
-// {
-// if (!ec)
-// {
-// resp_<< "All ok";
-// resp_.flush(req_);
-// }
-// }
-// private:
-// cgi::response& resp_;
-// boost::acgi::request& req_;
-// };
+// The styling information for the page.
+static const char* gCSS_text =
+"body { padding: 0; margin: 3%; border-color: #efe; }"
+".var_map_title"
+ "{ font-weight: bold; font-size: large; }"
+".var_map"
+ "{ border: 1px dotted; padding: 2px 3px 2px 3px; margin-bottom: 3%; }"
+".pair"
+ "{ border-top: 1px dotted; overflow: auto; padding: 0; margin: 0; }"
+/*
+".name"
+ "{ position: relative; float: left; width: 30%; font-weight: bold; }"
+".value"
+ "{ position: relative; float: left; width: 65%; left: 1%;"
+ " border-left: 1px solid; padding: 0 5px 0 5px;"
+ " overflow: auto; white-space: pre; }"
+*/
+".info"
+"{"
+ "border-color: #ca3766;"
+ "border-width: 1px 0 1px 0;"
+ "border-style: solid;"
+ "padding: 2px 8px 2px 8px;"
+ "margin: 1em"
+"}"
+"#response"
+"{"
+ "text-align: center;"
+ "padding: 20px 30px 20px 30px;"
+ "margin: 1em;"
+ "border-width: 2px 0 2px 0;"
+ "border-style: solid;"
+ "border-color: #ca3766;"
+"}"
+".var_map_title"
+"{"
+ "font-weight: bold;"
+ "font-size: large;"
+"}"
+".var_map"
+"{"
+ "border: 1px dotted;"
+ "padding: 2px 3px 2px 3px;"
+ "margin: 15px 0 15px 0;"
+"}"
+".var_pair"
+"{"
+ "border-top: 1px dotted;"
+ "overflow: auto;"
+ "padding: 0;"
+ "margin: 0;"
+"}"
+".var_name"
+"{"
+ "position: relative;"
+ "float: left;"
+ "width: 30%;"
+ "font-weight: bold;"
+"}"
+".var_value"
+"{"
+ "position: relative;"
+ "float: left;"
+ "width: 65%;"
+ "left: 1%;"
+ "border-left: 1px solid;"
+ "padding: 0 5px 0 5px;"
+ "overflow: auto;"
+ "white-space: pre;"
+"}"
+".nvpair"
+"{"
+ "list-style-type: none;"
+"}"
+"form"
+"{"
+// "width: 450px;"
+"}"
+"input"
+"{"
+"border-width: 0 0 1px 0;"
+"border-style: solid;"
+"border-color: #444;"
+"padding: 2px 3px 2px 3px;"
+"margin-left: 1em;"
+"background: #FaFbFd;"
+"}"
+"input[type=submit]"
+"{"
+ "margin-left: 35%;"
+"}"
+".name, .value"
+"{"
+ "display: inline;"
+ "width: 20%;"
+ "float: left;"
+"}"
+".name"
+"{"
+ "text-align: right;"
+ "padding-right: 1em;"
+ "clear: left;"
+"}"
+".value"
+"{"
+ "text-align: left;"
+ "padding-left: 1em;"
+"}"
+".clear { clear: both; }"
+".cookies { margin: 10px 0 25px 0; }"
+"#postform"
+"{"
+ "visibility: hidden;"
+ "display: none;"
+"}"
+;
+
+static const char* gJS_text =
+"function switch_method(ident) {"
+ "var f = document.getElementById(ident);"
+ "if (f.method == 'post') f.method = 'GET';"
+ "else f.method = 'POST';"
+"}"
+"function switch_value(elem) {"
+ "if (elem.value == 'Switch to POST') {"
+ "elem.value = 'Switch to GET';"
+ "}else{"
+ "elem.value = 'Switch to POST';"
+ "}"
+"}"
+"function switch_form(elem) {"
+ "var g = document.getElementById('getform');"
+ "var p = document.getElementById('postform');"
+ "if (elem.value == 'Switch to POST') {"
+ "p.style.visibility = 'visible';"
+ "p.style.display = 'block';"
+ "g.style.visibility = 'hidden';"
+ "g.style.display = 'none';"
+ "elem.value = 'Switch to GET';"
+ "} else {"
+ "g.style.visibility = 'visible';"
+ "g.style.display = 'block';"
+ "p.style.visibility = 'hidden';"
+ "p.style.display = 'none';"
+ "elem.value = 'Switch to POST';"
+ "}"
+"}"
+;
 
 /**
  * The following example has a few stages.
@@ -36,64 +156,97 @@
  * the source code.
  */
 
-int main()
+using namespace boost::acgi;
+
+template<typename Response, typename MapT>
+void print_formatted_data(Response& resp, MapT& data)
 {
- using namespace boost::acgi;
+ resp<< "<div class=\"cookies\">";
+ if (data.empty())
+ resp<< "<span class='value'>None found</span>";
+ else {
+ resp<< "<ul class=\"nvpair\">";
+ for(MapT::const_iterator iter=data.begin(), end = data.end(); iter != end; ++iter)
+ {
+ resp<< "<li class=\"name\">"
+ << iter->first
+ << "</li>"
+ "<li class=\"value\">"
+ << iter->second
+ << "</li>";
+ }
+ resp<< "</ul>"
+ "<div class=\"clear\"></div>";
+ }
+ resp<< "</div>";
+}
 
+int main()
+{
   service srv;
   request req(srv);
 
   // Load up the request data
- req.load(true);
+ req.load(parse_all);
 
   response resp;
+ resp<< content_type("text/plain");
 
- if (req[get]["reset"] == "true")
- {
- resp<< cookie("name").to_string()
- << location (req.script_name()) // redirect them.
- << content_type ("text/plain");
- resp.send(req.client());
- return 0;
- }
-
- // First, see if they have a cookie set
- std::string name = req[cookies]["name"];
- if (!name.empty())
+ if (has_key(req[form], "reset") && req[form]["reset"] == "true")
   {
- resp<< header("Content-type", "text/html")
- << "Hello again " << name << "<p />"
- << "<a href='?reset=true'><input type='submit' value='Reset' /></a>";
+ resp<< cookie("name")
+ << redirect(req, req.script_name()); // redirect them.
     resp.send(req.client());
     return 0;
   }
 
- // Now we'll check if they sent us a name in a form
- name = req[form_data]["name"];
- if (!name.empty())
+ if (has_key(req[form], "name"))
   {
- resp<< header("Content-type", "text/html")
- << cookie("name", name).to_string()
- << "Hello there, " << "<a href=''>" << name << "</a>";
- resp.send(req.client());
- return 0;
+ if (has_key(req[form], "del"))
+ resp<< cookie(req[form]["name"]);
+ else
+ resp<< cookie(req[form]["name"], req[form]["value"]);
+ resp<< redirect(req, req.script_name());
+ return_(resp, req, http::ok);
   }
 
- //std::string buf("Content-type: text/html\r\n\r\nHello there, Universe.<br />");
- //cgi::write(req, cgi::buffer(buf.c_str(), buf.size()));
-
   resp<< content_type("text/html")
- << "Hello there, Universe.<p />"
- << "What's your name?<br />";
+ << "<html>"
+ "<head>"
+ "<style type=\"text/css\">"
+ << gCSS_text
+ << "</style>"
+ "<script type=\"text/javascript\" language=\"Javascript\">"
+ << gJS_text
+ << "</script>"
+ "</head>"
+ "<body>";
 
- resp<< "<form method='POST'>"
- "<input name='name' type='text' value='" << req[form_data]["name"] << "'>"
- "</input>"
- "<input type='submit'></input>"
+ // First, see if they have a cookie set
+ if (has_key(req[cookies], "name"))
+ resp<< "<h1>Hello again " << req[cookies]["name"] << "</h1>"
+ << "<p><a href='?reset=true'><input type='submit' value='Reset' /></a></p>";
+ else
+ resp<< "<h1>Hello there.</h1>";
+
+ resp<< "<p>You can add cookies using the form below. If you add a cookie value for 'name', it will show up above.</p>"
+ "<p>Here is list of the cookies you currently have:</p>";
+
+ print_formatted_data(resp, req[cookies]);
+
+ resp<< "<form method='get' action='" << req.script_name() << "' id='getform'>"
+ "<label for='name' class='name'>Name:</label>"
+ "<input id='name' name='name' class='value' type='text' value='" << req[form]["name"] << "'>""</input>"
+ "<label for='value' class='name'>Value:</label>"
+ "<input id='value' name='value' class='value' type='text' value='" << req[form]["value"] << "'>""</input>"
+ "<label for='del' class='name'>Delete this cookie?</label>"
+ "<input id='del' name='del' class='value' type='checkbox'></input>"
+ "<div class='clear'></div>"
+ "<input type='submit'></input>"
          "</form>"
- << "<p><b>SCRIPT_NAME</b> = <i>" << req.script_name() << "</i></p>";
+ "<input type='submit' onclick='switch_method(\"getform\"); switch_value(this); return false;' value='Switch to POST'></input>"
+ "</body>"
+ "</html>";
 
- resp.send(req.client());
-
- return 0;
-}
+ return_(resp, req, http::ok);
+}
\ No newline at end of file

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/acgi/echo/main.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -93,7 +93,7 @@
     try {
 
       boost::system::error_code ec;
- req.load(ec, parse_all); // parse everything.
+ req.load(parse_all, ec); // parse everything.
 
       if (ec)
       {

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/Jamfile.v2 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,29 @@
+# Copyright (c) 2007 Darren Garvey
+#
+# 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)
+
+project boost/cgi/example/cgi/tracing_server ;
+
+exe cgi_debug_server
+ :
+ hello.cpp
+ Timer.hpp
+ TracingServer.cpp
+ TracingServer.hpp
+ :
+ <library>/boost/cgi/
+ ;
+
+
+# Our install rule (builds binaries and copies them to <location>)
+install install
+ :
+ cgi_debug_server
+ :
+ <location>$(cgi-bin)
+ ;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install ;

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/Timer.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/Timer.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,30 @@
+
+#undef max
+#undef min
+#include <boost/chrono/chrono.hpp>
+
+//using namespace boost::chrono;
+
+template< class Clock >
+class Timer
+{
+ typename Clock::time_point start;
+public:
+
+ Timer() : start( Clock::now() ) {}
+
+ typename Clock::duration elapsed() const
+ {
+ return Clock::now() - start;
+ }
+
+ double seconds() const
+ {
+ return elapsed().count() * ((double)Clock::period::num/Clock::period::den);
+ }
+
+ double latency() const
+ {
+ return (-(Clock::now() - Clock::now())).count();
+ }
+};

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/TracingServer.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/TracingServer.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,262 @@
+#include "TracingServer.hpp"
+#include <boost/chrono/chrono.hpp>
+#include <typeinfo>
+
+namespace detail {
+
+// The styling information for the page.
+static const char* gCSS_text =
+//"body { padding: 0; margin: 3%; border-color: #efe; }"
+".info"
+"{"
+ "border-color: #ca3766;"
+ "border-width: 1px 0 1px 0;"
+ "border-style: solid;"
+ "padding: 2px 8px 2px 8px;"
+ "margin: 1em"
+"}"
+"#response"
+"{"
+ "text-align: center;"
+ "padding: 20px 30px 20px 30px;"
+ "margin: 1em;"
+ "border-width: 2px 0 2px 0;"
+ "border-style: solid;"
+ "border-color: #ca3766;"
+"}"
+".var_map_title"
+"{"
+ "font-weight: bold;"
+ "font-size: large;"
+"}"
+".var_map"
+"{"
+ "border: 1px dotted;"
+ "padding: 2px 3px 2px 3px;"
+ "margin: 15px 0 15px 0;"
+"}"
+".var_pair"
+"{"
+ "border-top: 1px dotted;"
+ "overflow: auto;"
+ "padding: 0;"
+ "margin: 0;"
+"}"
+".var_name"
+"{"
+ "position: relative;"
+ "float: left;"
+ "width: 30%;"
+ "font-weight: bold;"
+"}"
+".var_value"
+"{"
+ "position: relative;"
+ "float: left;"
+ "width: 65%;"
+ "left: 1%;"
+ "border-left: 1px solid;"
+ "padding: 0 5px 0 5px;"
+ "overflow: auto;"
+ "white-space: pre;"
+"}"
+"ul.nvpair"
+"{"
+ "list-style-type: none;"
+ "padding: 0;"
+ "margin: 0;"
+"}"
+"ul.nvpair li"
+"{"
+ "display: inline;"
+ "width: 175px;"
+ "float: left;"
+"}"
+"ul.nvpair li.name"
+"{"
+ "text-align: right;"
+ "padding-right: 1em;"
+ "clear: left;"
+"}"
+"ul.nvpair li.value"
+"{"
+ "text-align: left;"
+ "padding-left: 1em;"
+"}"
+".clear { clear: both; }"
+;
+
+
+//
+// This function writes the title and map contents to the ostream in an
+// HTML-encoded format (to make them easier on the eye).
+//
+template<typename OStreamT, typename MapT>
+void format_map(OStreamT& os, MapT& m, const std::string& title)
+{
+ os<< "<div class=\"var_map\">"
+ "<div class=\"var_map_title\">"
+ << title
+ << "</div><ul>";
+
+ if (m.empty())
+ os<< "<ul class=\"var_pair\">EMPTY</ul>";
+ else
+ for (typename MapT::const_iterator i = m.begin(); i != m.end(); ++i)
+ {
+ os<< "<li class=\"var_pair\">"
+ "<div class=\"var_name\">"
+ << i->first
+ << "</div>"
+ "<div class=\"var_value\">"
+ << i->second
+ << "</div>"
+ "</li>";
+ }
+ os<< "</ul></div>";
+}
+
+boost::uint64_t
+get_microseconds(boost::chrono::process_clock::duration& tp)
+{
+ return boost::chrono::duration_cast<boost::chrono::microseconds>(tp).count();
+}
+
+}
+
+TracingServer::TracingServer(void)
+ : timer_()
+{
+}
+
+TracingServer::~TracingServer(void)
+{
+}
+
+void TracingServer::bomb_out(std::string const& error, response_type& response, request_type& request)
+{
+ boost::chrono::process_times times;
+ timer_.elapsed(times);
+ response_type resp2;
+ resp2<< boost::cgi::content_type("text/html")
+ << "<html>"
+ "<head>"
+ "<title>CGI Echo Example</title>"
+ "<style type=\"text/css\">"
+ << detail::gCSS_text <<
+ "</style>"
+ "<head>"
+ "<body>"
+ "<p style='font-weight: bold'>"
+ "<h1 style='font-size: x-large'>Problem found.</h1>"
+ "<p>The original response follows, after some details about the error that occurred and the request that caused it</p>"
+ "<p>First, the error that we tried to detect:</p>"
+ "</p>"
+ "<div class=\"info\">"
+ << error
+ << "</div>"
+ "The request took the following time to process:"
+ "<div class=\"info\">"
+ "<ul class='nvpair'>"
+ "<li class='name'>Real time</li>"
+ "<li class='value'>" << detail::get_microseconds(times.real) << " microseconds</li>"
+
+ "<li class='name'>User time</li>"
+ "<li class='value'>" << detail::get_microseconds(times.user) << " microseconds</li>"
+
+ "<li class='name'>System time</li>"
+ "<li class='value'>" << detail::get_microseconds(times.system) << " microseconds</li>"
+ "</ul>"
+ "<br class='clear' />"
+ "</div>"
+
+ "Some details about the request:"
+ "<div class=\"info\">";
+ //style='"
+ // "border-color: #ca3766;" "border-width: 1px 0 1px 0;" "border-style: solid;"
+ // "padding: 2px 8px 2px 8px;" "margin: 1em" "'>";
+ detail::format_map(resp2, request[boost::cgi::env], "Env data");
+ //detail::format_map(resp2, request[boost::cgi::env_map], "Env data");
+ detail::format_map(resp2, request[boost::cgi::form], "Form (" + request.request_method() + ") data");
+ detail::format_map(resp2, request[boost::cgi::cookies], "Cookies");
+ resp2<< "</div>"
+ "<p>The headers sent in the original (broken) response were:</p>"
+ "<div class=\"info\">"
+ "<pre style='white-space:pre; padding-left: 3em; margin-left: 1em'>"
+ "<ul>";
+ BOOST_FOREACH(std::string& hstring, response.headers())
+ {
+ resp2<< "<li>" << hstring << "</li>";
+ }
+ resp2<< "</ul>"
+ << "</pre>"
+ "</div>"
+ "Below is the original response (inside borders, with (x=30;y=20)px of padding):"
+ "<div id='response'>"
+ << response // print out the original response
+ << "</div>"
+ "</body>"
+ "</html>";
+ resp2.send(request.client());
+ request.close();
+}
+
+void TracingServer::bomb_out(boost::system::system_error* err, response_type& response, request_type& request) {
+ typedef request_type::string_type string;
+ string err_msg("<ul class=nvpair>boost::system::system_error*<li class=name>Code:</li>");
+ err_msg += string("<li class=value>") + boost::lexical_cast<std::string>(err->code()) + "</li>"
+ + "<li class=name>What:</li>"
+ + "<li class=value>" + err->what() + "</li>"
+ + "<li class=name>Type:</li>"
+ + "<li class=value>" + typeid(err).name() + "</li><br class=clear /></ul>";
+ bomb_out(err_msg, response, request);
+}
+
+void TracingServer::bomb_out(std::exception* e, response_type& response, request_type& request) {
+ typedef request_type::string_type string;
+ string err_msg("<ul class=nvpair>std::exception*<li class=name>What:</li>");
+ err_msg += string("<li class=value>") + e->what() + "</li>"
+ + "<li class=name>Type:</li>"
+ + "<li class=value>" + typeid(e).name() + "</li><br class=clear /></ul>";
+ bomb_out(err_msg, response, request);
+}
+
+void TracingServer::bomb_out(std::exception& e, response_type& response, request_type& request) {
+ typedef request_type::string_type string;
+ string err_msg("<ul class=nvpair>std::exception<li class=name>What:</li>");
+ err_msg += string("<li class=value>") + e.what() + "</li>"
+ + "<li class=name>Type:</li>"
+ + "<li class=value>" + typeid(e).name() + "</li><br class=clear /></ul>";
+ bomb_out(err_msg, response, request);
+}
+
+bool TracingServer::run(callback_type const& callback)
+{
+ timer_.start();
+ request_type request;
+ response_type response;
+ try {
+ request.load(boost::cgi::parse_all);
+ int ret(callback(request, response));
+ if (request[boost::cgi::form]["debug"] == "1") {
+ bomb_out("** Debug mode ** - client callback returned code #" + boost::lexical_cast<std::string>(ret)
+ , response, request);
+ }else
+ if (!ret) {
+ response.send(request.client());
+ request.close();
+ return true;
+ } else {
+ bomb_out("Callback returned code #" + boost::lexical_cast<std::string>(ret) + "; unknown error", response, request);
+ }
+ }catch(boost::system::system_error* err) {
+ bomb_out(err, response, request); return false;
+ }catch(std::exception* e) {
+ bomb_out(e, response, request); return false;
+ }catch(std::exception& e) {
+ bomb_out(e, response, request); return false;
+ }catch(...){
+ bomb_out("Unknown error (captor: CGI hello example TracingServer::run())", response, request); return false;
+ }
+ return false;
+}

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/TracingServer.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/TracingServer.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <iostream>
+#include <boost/function.hpp>
+#include <boost/cgi/cgi.hpp>
+#undef min
+#undef max
+#include <boost/chrono/process_times.hpp>
+
+//#include <boost/chrono/chrono.hpp>
+
+/// A server which catches some runtime errors in your app.
+/**
+ * This server traces each request and dumps helpful info to a browser if
+ * an error occurs. The errors which are acknowledged at the moment are
+ * exceptions and your handler returning non-zero. You can fake an error
+ * by appending 'debug=1' to the passed form variables.
+ *
+ * When an error is caught, details about that, the request that caused it and
+ * the response (along with headers) are dumped to the client in a browser-
+ * friendly way,
+ *
+ */
+class TracingServer
+{
+ typedef boost::cgi::request request_type;
+ typedef boost::cgi::response response_type;
+ typedef boost::function<int (request_type&, response_type&)> callback_type;
+ //typedef Timer<boost::chrono::high_resolution_clock> timer_type;
+ typedef boost::chrono::process_timer timer_type;
+
+ timer_type timer_;
+public:
+ TracingServer(void);
+ ~TracingServer(void);
+
+ bool run(callback_type const& callback);
+
+ void bomb_out(std::string const& error, response_type&, request_type&);
+ void bomb_out(boost::system::system_error* err, response_type&, request_type&);
+ void bomb_out(std::exception* e, response_type&, request_type&);
+ void bomb_out(std::exception& e, response_type&, request_type&);
+};

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/hello.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer/hello.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,64 @@
+// hello.cpp : Defines the entry point for the application.
+//
+
+#include <iostream>
+
+// Include the CGI headers.
+#include <boost/cgi/cgi.hpp>
+// Include the utilities (ie. has_key)
+#include <boost/cgi/utility.hpp>
+// Uses a server class that catches and reports errors in your handler.
+#include "TracingServer.hpp"
+
+using boost::cgi::form;
+using boost::cgi::request;
+using boost::cgi::response;
+using boost::cgi::header;
+using boost::cgi::content_type;
+
+
+int cgi_handler(request& req, response& resp)
+{
+ resp<< header("X-Custom-Header: some value")
+ << content_type("text/html")
+ << "<html>"
+ "<head>"
+ "<title>Debug Server</title>"
+ "</head>"
+ "<body>"
+ "<h1>Debugging Server Example</h1>"
+ "<p>"
+ "The server used in this example will catch exceptions thrown by "
+ "your request handler, or a non-zero return value. It will print "
+ "some presumably helpful info about what might have caused the "
+ "problem - obviously this is just an example, which you'd "
+ "probably want to ammend."
+ "</p>"
+ "<p>"
+ "The handler in this example will throw a std::runtime_error if "
+ "you pass 'badger=bait!' to the script, for example by following "
+ "<a href=\"?badger=bait%21\">this link</a>."
+ "</p>"
+ "<p>"
+ "The handler in this example will also return false if you pass "
+ "pass 'spam' to the script, for example by clicking "
+ "<a href=\"?spam\">here</a>."
+ "</p>"
+ "<p>"
+ "Finally, you can simulate an error and get traceback details "
+ "regardless of whether the script completed by passing 'debug=1',"
+ " or by following <a href=\"?debug=1\">this link</a>."
+ "</p>"
+ "</body>"
+ "</html>";
+ if (req[form]["badger"] == "bait!") throw std::runtime_error("AOUHFAEOUHAEOUHAEOUHOUH!!!!!!");
+ else if (has_key(req[form], "spam")) return 33;
+ return 0;
+}
+
+int main()
+{
+ TracingServer server;;
+ server.run(&cgi_handler);
+ return 0;
+}

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/TracebackServer.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/TracebackServer.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,143 @@
+#include "TracebackServer.hpp"
+#include <boost/chrono/chrono.hpp>
+
+#define TBS_TEMPLATE__DEBUG_VIEW "../templates/debug_view.html"
+
+namespace detail {
+
+boost::uint64_t
+get_microseconds(boost::chrono::process_clock::duration& tp)
+{
+ return boost::chrono::duration_cast<boost::chrono::microseconds>(tp).count();
+}
+
+} // namespace detail
+
+
+TracebackServer::TracebackServer(void)
+ : timer_()
+{
+}
+
+TracebackServer::~TracebackServer(void)
+{
+}
+
+template<typename MapT>
+void TracebackServer::expand_map(dictionary_type& dict, MapT& data, std::string const& title)
+{
+ dictionary_type* sub_dict = dict.AddSectionDictionary("REQUEST_DATA_MAP");
+ sub_dict->SetValue("REQUEST_DATA_MAP_TITLE", title);
+ if (data.empty())
+ sub_dict->ShowSection("REQUEST_DATA_MAP_EMPTY");
+ else {
+ for(typename MapT::const_iterator iter(data.begin()), end(data.end()); iter != end; ++iter)
+ {
+ dictionary_type* nvpair_dict = sub_dict->AddSectionDictionary("REQUEST_DATA_PAIR");
+ nvpair_dict->SetValue("REQUEST_DATA_NAME", iter->first.c_str());
+ nvpair_dict->SetValue("REQUEST_DATA_VALUE", iter->second);
+ }
+ }
+}
+
+void TracebackServer::stop_timer()
+{
+ timer_.elapsed(stop_times_);
+}
+
+void TracebackServer::dump_times(dictionary_type& dict)
+{
+ dict.ShowSection("RUNNING_TIME");
+ dict.SetValue("RUNNING_TIME_RESOLUTION", "microseconds");
+ dict.SetFormattedValue("REAL_TIME", "%d us", detail::get_microseconds(stop_times_.real));
+ dict.SetFormattedValue("CPU_TIME", "%d us", detail::get_microseconds(stop_times_.user + stop_times_.system));
+ dict.SetFormattedValue("USER_TIME", "%d us", detail::get_microseconds(stop_times_.user));
+ dict.SetFormattedValue("SYSTEM_TIME", "%d us", detail::get_microseconds(stop_times_.system));
+}
+
+void TracebackServer::bomb_out(std::string const& error, response_type& response, request_type& request)
+{
+ stop_timer();
+ response_type resp2;
+ template_ = google::Template::GetTemplate(TBS_TEMPLATE__DEBUG_VIEW, google::STRIP_WHITESPACE);
+ dictionary_type dict("debug_view");
+ dict.SetValue("ERROR", error);
+ expand_map(dict, request[boost::cgi::env], "Environment Data");
+ expand_map(dict, request[boost::cgi::form], "Form (" + request.request_method() + ") data");
+ expand_map(dict, request[boost::cgi::cookies], "Cookies");
+ BOOST_FOREACH(std::string& hstring, response.headers())
+ {
+ dict.SetValueAndShowSection("HEADER", hstring, "RESPONSE_HEADER");
+ }
+ dump_times(dict);
+
+ //dict.SetValue("ORIGINAL_RESPONSE", response.rdbuf()->data());
+ std::string debug_output;
+ template_->Expand(&debug_output, &dict);
+ resp2<< boost::cgi::content_type("text/html")
+ << debug_output
+ << response;
+ resp2.send(request.client());
+ request.close();
+}
+
+
+void TracebackServer::bomb_out(boost::system::system_error* err, response_type& response, request_type& request) {
+ typedef request_type::string_type string;
+ string err_msg("<ul class=nvpair>boost::system::system_error*<li class=name>Code:</li>");
+ err_msg += string("<li class=value>") + boost::lexical_cast<std::string>(err->code()) + "</li>"
+ + "<li class=name>What:</li>"
+ + "<li class=value>" + err->what() + "</li>"
+ + "<li class=name>Type:</li>"
+ + "<li class=value>" + typeid(*err).name() + "</li><br class=clear /></ul>";
+ bomb_out(err_msg, response, request);
+}
+
+void TracebackServer::bomb_out(std::exception* e, response_type& response, request_type& request) {
+ typedef request_type::string_type string;
+ string err_msg("<ul class=nvpair>std::exception*<li class=name>What:</li>");
+ err_msg += string("<li class=value>") + e->what() + "</li>"
+ + "<li class=name>Type:</li>"
+ + "<li class=value>" + typeid(*e).name() + "</li><br class=clear /></ul>";
+ bomb_out(err_msg, response, request);
+}
+
+void TracebackServer::bomb_out(std::exception& e, response_type& response, request_type& request) {
+ typedef request_type::string_type string;
+ string err_msg("<ul class=nvpair>std::exception<li class=name>What:</li>");
+ err_msg += string("<li class=value>") + e.what() + "</li>"
+ + "<li class=name>Type:</li>"
+ + "<li class=value>" + typeid(e).name() + "</li><br class=clear /></ul>";
+ bomb_out(err_msg, response, request);
+}
+
+bool TracebackServer::run(callback_type const& callback)
+{
+ timer_.start();
+ request_type request;
+ response_type response;
+ try {
+ request.load(boost::cgi::parse_all);
+ int ret(callback(request, response));
+ if (request[boost::cgi::form_data]["debug"] == "1") {
+ bomb_out("** Debug mode ** - client callback returned code #" + boost::lexical_cast<std::string>(ret)
+ , response, request);
+ }else
+ if (!ret) {
+ response.send(request.client());
+ request.close();
+ return true;
+ } else {
+ bomb_out("Callback returned code #" + boost::lexical_cast<std::string>(ret) + "; unknown error", response, request);
+ }
+ }catch(boost::system::system_error* err) {
+ bomb_out(err, response, request); return false;
+ }catch(std::exception* e) {
+ bomb_out(e, response, request); return false;
+ }catch(std::exception& e) {
+ bomb_out(e, response, request); return false;
+ }catch(...){
+ bomb_out("Unknown exception (captor: CGI hello example TracebackServer::run())", response, request); return false;
+ }
+ return false;
+}

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/TracebackServer.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/TracebackServer.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <iostream>
+#include <boost/function.hpp>
+#include <boost/cgi/cgi.hpp>
+#undef min
+#undef max
+#include <boost/chrono/process_times.hpp>
+#include <google/template.h>
+//#include <boost/chrono/chrono.hpp>
+
+/// A server which catches some runtime errors in your app.
+/**
+ * This server traces each request and dumps helpful info to a browser if
+ * an error occurs. The errors which are acknowledged at the moment are
+ * exceptions and your handler returning non-zero. You can fake an error
+ * by appending 'debug=1' to the passed form variables.
+ *
+ * When an error is caught, details about that, the request that caused it and
+ * the response (along with headers) are dumped to the client in a browser-
+ * friendly way,
+ *
+ */
+class TracebackServer
+{
+ typedef boost::cgi::request request_type;
+ typedef boost::cgi::response response_type;
+ typedef boost::function<int (request_type&, response_type&)> callback_type;
+ //typedef Timer<boost::chrono::high_resolution_clock> timer_type;
+ typedef boost::chrono::process_timer timer_type;
+ typedef google::Template template_type;
+ typedef google::TemplateDictionary dictionary_type;
+
+ timer_type timer_;
+ template_type* template_;
+ boost::chrono::process_times stop_times_;
+public: // member variables
+ bool show_times;
+public:
+ TracebackServer(void);
+ ~TracebackServer(void);
+
+ bool run(callback_type const& callback);
+
+ void bomb_out(std::string const& error, response_type&, request_type&);
+ void bomb_out(boost::system::system_error* err, response_type&, request_type&);
+ void bomb_out(std::exception* e, response_type&, request_type&);
+ void bomb_out(std::exception& e, response_type&, request_type&);
+
+ //dictionary_type& new_dictionary(std::string const& name);
+ template<typename MapT>
+ void expand_map(dictionary_type& dict, MapT& data, std::string const& title);
+
+ void stop_timer();
+
+ // Add the running times to the dictionary.
+ void dump_times(dictionary_type& dict);
+};
\ No newline at end of file

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/ctemplate.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/ctemplate.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,67 @@
+
+#include <iostream>
+#include <boost/cgi/cgi.hpp>
+#include <boost/cgi/utility.hpp>
+#include <google/template.h>
+#include "TracebackServer.hpp"
+#include <cmath>
+
+using boost::cgi::form;
+using boost::cgi::request;
+using boost::cgi::response;
+using boost::cgi::header;
+using boost::cgi::content_type;
+
+
+int cgi_handler(request& req, response& resp)
+{
+ /*
+ for(long i=10000000; i != 0; --i)
+ {
+ std::sqrt(123.456L); // waste time
+ }
+ */
+ resp<< header("X-Custom-Header: some value")
+ << content_type("text/html")
+ << "<html>"
+ "<head>"
+ "<title>Debug Server</title>"
+ "</head>"
+ "<body>"
+ "<h1>Debugging Server Example</h1>"
+ "<p>"
+ "The server used in this example will catch exceptions thrown by "
+ "your request handler, or a non-zero return value. It will print "
+ "some presumably helpful info about what might have caused the "
+ "problem - obviously this is just an example, which you'd "
+ "probably want to ammend."
+ "</p>"
+ "<p>"
+ "The handler in this example will throw a std::runtime_error if "
+ "you pass 'badger=bait!' to the script, for example by following "
+ "<a href=\"?badger=bait%21\">this link</a>."
+ "</p>"
+ "<p>"
+ "The handler in this example will also return false if you pass "
+ "pass 'spam' to the script, for example by clicking "
+ "<a href=\"?spam=1\">here</a>."
+ "</p>"
+ "<p>"
+ "Finally, you can simulate an error and get traceback details "
+ "regardless of whether the script completed by passing 'debug=1',"
+ " or by following <a href=\"?debug=1\">this link</a>."
+ "</p>"
+ "</body>"
+ "</html>";
+ if (req[form]["badger"] == "bait!") throw std::runtime_error("AOUHFAEOUHAEOUHAEOUHOUH!!!!!!");
+ else if (has_key(req[form], "spam")) return 33;
+ return 0;
+}
+
+int main(int, char**)
+{
+ TracebackServer server;;
+ server.run(&cgi_handler);
+
+ return 0;
+}
\ No newline at end of file

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.css
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.css 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,106 @@
+
+.info
+{
+ border-color: #ca3766;
+ border-width: 1px 0 1px 0;
+ border-style: solid;
+ padding: 2px 8px 2px 8px;
+ margin: 1em
+}
+#response
+{
+ text-align: center;
+ padding: 20px 30px 20px 30px;
+ margin: 1em;
+ border-width: 2px 0 2px 0;
+ border-style: solid;
+ border-color: #ca3766;
+}
+.var_map_title
+{
+ font-weight: bold;
+ font-size: large;
+}
+.var_map
+{
+ border: 1px dotted;
+ padding: 2px 3px 2px 3px;
+ margin: 15px 0 15px 0;
+}
+.var_pair
+{
+ border-top: 1px dotted;
+ overflow: auto;
+ padding: 0;
+ margin: 0;
+}
+.var_name
+{
+ position: relative;
+ float: left;
+ width: 30%;
+ font-weight: bold;
+}
+.var_value
+{
+ position: relative;
+ float: left;
+ width: 65%;
+ left: 1%;
+ border-left: 1px solid;
+ padding: 0 5px 0 5px;
+ overflow: auto;
+ white-space: pre;
+}
+ul.nvpair
+{
+ list-style-type: none;
+ overflow: hidden;
+}
+ul.nvpair li
+{
+ display: inline;
+ width: 175px;
+ float: left;
+}
+ul.nvpair li.name
+{
+ text-align: right;
+ padding-right: 1em;
+ clear: left;
+}
+ul.nvpair li.value
+{
+ text-align: left;
+ padding-left: 1em;
+}
+.clear { clear: both; }
+.bold { font-weight: bold; }
+
+.debuginfo
+{
+ position: fixed;
+ right: 0;
+ border-style: double;
+ border-width: 0 0 4px 4px;
+ border-color: #ca3766;
+ font-size: x-small;
+ top: 0;
+ text-align: center;
+ -moz-border-radius-bottomleft: 15px;
+ opacity: 0.9;
+ background: #fbfbfb;
+}
+
+.debuginfo ul.nvpair li.value
+{
+ margin: 0;
+ width: 9em;
+}
+
+.debuginfo ul.nvpair li.name
+{
+ margin: 0;
+ padding: 0;
+ width: 3em;
+}
\ No newline at end of file

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.html
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.html 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1,66 @@
+
+
+<html>
+<head>
+<title>CGI Echo Example (using Google cTemplate)</title>
+<link rel="stylesheet" type="text/css" href="/css/debug_view.css" />
+</head>
+<body>
+
+{{#RUNNING_TIME}}
+<div class="debuginfo">
+ Run time ({{RUNNING_TIME_RESOLUTION}}):
+ <ul class="nvpair">
+ <li class="name">Real</li><li class="value">{{REAL_TIME}}</li>
+ <li class="name">CPU</li><li class="value">{{CPU_TIME}}</li>
+ <li class="name">User</li><li class="value">{{USER_TIME}}</li>
+ <li class="name">System</li><li class="value">{{SYSTEM_TIME}}</li>
+ </ul>
+</div>
+{{/RUNNING_TIME}}
+
+<p class="bold">
+ <h1>Problem found.</h1>
+ <p>The original response follows, after some details about the error that occurred and the request that caused it</p>
+ <p>First, the error that we tried to detect:</p>
+</p>
+<div class="info">
+ {{ERROR}}
+</div>
+
+Some details about the request:
+
+<div class="info">
+{{#REQUEST_DATA_MAP}}
+<div class="var_map">
+ <div class="var_map_title">
+ {{REQUEST_DATA_MAP_TITLE}}
+ </div>
+ <ul>
+ {{#REQUEST_DATA_MAP_EMPTY}}
+ <li class="var_pair">EMPTY</li>
+ {{/REQUEST_DATA_MAP_EMPTY}}
+ {{#REQUEST_DATA_PAIR}}
+ <li class="var_pair">
+ <div class="var_name">{{REQUEST_DATA_NAME:h}}</div>
+ <div class="var_value">{{REQUEST_DATA_VALUE:h}}</div>
+ </li>
+ {{/REQUEST_DATA_PAIR}}
+ </ul>
+</div>
+{{/REQUEST_DATA_MAP}}
+</div>
+
+The headers sent in the original (broken) response were:
+<div class="info">
+ <pre style="white-space:pre; padding-left: 3em; margin-left: 1em">
+ <ul>{{#RESPONSE_HEADER}}<li>{{HEADER:h}}</li>{{/RESPONSE_HEADER}}</ul>
+ </pre>
+</div>
+
+Below is the original response (take into account that it may not look as it should):
+<div class="clear"></div>
+
+</body>
+
+</html>
\ No newline at end of file

Added: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.js
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/DebugServer2/debug_view.js 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -0,0 +1 @@
+

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/Jamfile.v2 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -7,6 +7,7 @@
 # By default, just build the examples
 build-project hello_world ;
 build-project echo ;
+build-project tracing_server ;
 
 # If the user explicitly passes "install" on the command line, build the
 # CGI examples and copy them to $(cgi-bin)
@@ -14,6 +15,7 @@
   :
     hello_world
     echo
+ tracing_server
   :
     <location>$(cgi-bin)
   ;

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/cgi/hello_world/main.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -11,6 +11,9 @@
 //
 // The simplest CGI program, outputs only "Hello there, universe."
 //
+// If you think this is a pointless example, try getting it to work;
+// It doesn't always go to plan... ;)
+//
 
 #include <boost/cgi/cgi.hpp>
 

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/xcgi/server1/Server.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/xcgi/server1/Server.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/xcgi/server1/Server.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -3,6 +3,7 @@
 
 //[xcgi_server1_server
 #include <boost/cgi.hpp>
+#include <boost/cgi/fcgi.hpp>
 
 class Server
 {

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/src/library_sources.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/src/library_sources.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/src/library_sources.cpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -8,8 +8,8 @@
  * eg.
  * libs/cgi/build$ bjam --build-cgi (builds the library)
  *
- * libs/cgi/example$ bjam --build-cgi install
- *
+ * libs/cgi/example$ bjam --build-cgi install
+ *
  * (builds and installs all the examples using the compiled binary
  * - which will be installed if necessary - see the docs for more)
  *
@@ -33,4 +33,3 @@
 //#include <boost/cgi/impl/response.ipp>
 #include <boost/cgi/impl/fcgi_request_service.ipp>
 #include <boost/cgi/detail/url_decode.ipp>
-

Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/test/run/request_test_template.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/test/run/request_test_template.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/test/run/request_test_template.hpp 2009-01-31 07:18:42 EST (Sat, 31 Jan 2009)
@@ -5,13 +5,13 @@
   BOOST_CHECK( req[env_data].size() ); \
   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]["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]["http_host"], "localhost" ); \
   /* Check helper function (need to test them all?) */ \
- BOOST_CHECK_EQUAL( req.script_name(), "some/test/script" );
+ BOOST_CHECK_EQUAL( req.script_name(), "some/test/script" );
 
 
 #define TEST_GET_DATA(req) \
@@ -36,14 +36,14 @@
     /* Check cookie parsing */ \
     BOOST_CHECK( req[cookies].size() ); \
     BOOST_CHECK_EQUAL( req[cookies]["foo"], "bar" ); \
- /* Check case-insensitive name comparing */ \
+ /* Check case-insensitive name comparison */ \
     BOOST_CHECK_EQUAL( req[cookies]["FOO"], "bar" );
 
 #define TEST_TWO_COOKIES(req) \
                                                                                 \
     BOOST_CHECK_EQUAL( req[cookies]["foo"], "bar" ); \
     BOOST_CHECK_EQUAL( req[cookies]["another_one"], "stuff" );
-
+
 #define TEST_ENCODED_COOKIE(req) \
                                                                                 \
     BOOST_CHECK_EQUAL( req[cookies]["foo"], "bar" ); \
@@ -58,7 +58,7 @@
   // MSVC doesn't support setenv, but it does support putenv
   void setenv(std::string const& name, std::string const& val, int reset = 0)
   {
-
+
     //char *envvar = new char["
     if (0 != _putenv((name + "=" + val).c_str()))
     {


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