$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: lists.drrngrvy_at_[hidden]
Date: 2008-03-31 23:29:42
Author: drrngrvy
Date: 2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
New Revision: 43979
URL: http://svn.boost.org/trac/boost/changeset/43979
Log:
* Moved multipart/form-data parsing into separate form_parser class. It's only a crude start, but it works as well as before (maybe very slightly better).
* Emptied request_ostream.hpp (should be gone soon).
* Fixed connections/stdio.hpp - the last updates didn't actually use it properly so the problems with it didn't show up... Should work fine now, slightly better than when using std::cin functions.
Text files modified: 
   sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp                 |    18 +                                       
   sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp                |    10                                         
   sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_sync_io_object.hpp         |     1                                         
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp           |   407 ++++++++++++++++++++++++++++++++++++++- 
   sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp            |    44 ++--                                    
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp |   184 ++++++-----------                       
   sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp         |    16                                         
   sandbox/SOC/2007/cgi/trunk/boost/cgi/request_ostream.hpp              |     7                                         
   8 files changed, 515 insertions(+), 172 deletions(-)
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_client.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -17,6 +17,7 @@
 #include "boost/cgi/http/status_code.hpp"
 #include "boost/cgi/connections/tcp_socket.hpp"
 
+
 namespace cgi {
  namespace common {
 
@@ -110,9 +111,20 @@
     std::size_t read_some(const MutableBufferSequence& buf
                          , boost::system::error_code& ec)
     {
-      std::size_t bytes_read = connection_->read_some(buf, ec);
-      bytes_left_ -= bytes_read;
-      return bytes_left_ > 0 ? bytes_read : (bytes_read + bytes_left_);
+      //if (boost::asio::buffer_size(buf) > bytes_left_)
+      //{
+        std::size_t bytes_read = connection_->read_some(buf, ec);
+        bytes_left_ -= bytes_read;
+        if (ec == boost::asio::error::eof)
+          ec = boost::system::error_code();
+        return bytes_left_ > 0 ? bytes_read : (bytes_read + bytes_left_);
+      //}
+      //else
+      //{
+      //  
+      //  ec = boost::asio::error::eof;
+      //  return 0;
+      //}
     }
 
     /// Asynchronously write some data to the client.
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -642,12 +642,6 @@
       this->service.set_status(this->implementation, status);
     }
 
-    // The boundary marker for multipart forms (this is likely a transient function).
-    std::string boundary_marker()
-    {
-      return this->implementation.boundary_marker;
-    }
-
     map_type& operator[](common::data_source source)
     {
       switch(source)
@@ -657,9 +651,11 @@
       case cookie_data: return this->implementation.cookie_vars_;
       case env_data:    return this->implementation.env_vars_;
       case form_data:
+      default:
         std::string rm( request_method() );
-        if (rm == "GET") return this->implementation.get_vars_;
+        if (rm == "GET")       return this->implementation.get_vars_;
         else if (rm == "POST") return this->implementation.post_vars_;
+        else                   return this->implementation.env_vars_;
       }
     }
   };
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_sync_io_object.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_sync_io_object.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_sync_io_object.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -26,7 +26,6 @@
   protected:
     explicit basic_sync_io_object()
     {
-      std::cerr<< "Hello";
       service.construct(implementation);
     }
 
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -6,39 +6,420 @@
 #include <set>
 #include <vector>
 #include <string>
+#include <boost/regex.hpp>
 #include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
 #include <boost/function.hpp>
+#include <boost/system/error_code.hpp>
 #include "boost/cgi/common/form_part.hpp"
+#include "boost/cgi/basic_client.hpp"
 
 namespace cgi {
  namespace detail {
 
-  /// Destined for greater things than an implementation detail.
+  /// Destined for better things than an implementation detail (hopefully).
+  template<typename RequestImplType>
   class form_parser
   {
   public:
-    typedef
-      boost::function<
-        std::size_t (
-            const boost::asio::mutable_buffer&
-          , boost::system::error_code& )
-      >
-    callback_type;
+    //typedef
+    //  boost::function<
+    //    std::size_t (
+    //        const mutable_buffers_type&
+    //      , boost::system::error_code& )
+    //  >
+    //callback_type;
 
-    typedef std::vector<char> buffer_type;
+    typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+    typedef std::vector<char>   buffer_type;
+    typedef ::cgi::common::map  map_type;
 
-    form_parser()
+    typedef RequestImplType     implementation_type;
+
+    implementation_type& impl_;
+    std::size_t& bytes_left_;
+    buffer_type::iterator pos_;
+    bool& stdin_data_read_;
+    std::size_t offset_;
+
+    std::string boundary_marker;
+    std::list<std::string> boundary_markers;
+    std::vector<common::form_part> form_parts_;
+
+    form_parser(implementation_type& impl)
+      : impl_(impl)
+      , bytes_left_(impl.characters_left_)
+      , stdin_data_read_(impl.stdin_data_read_)
+      , offset_(0)
+    {
+    }
+    /*
+    form_parser(std::size_t& cl, buffer_type& buf, map_type& m
+               , unsigned int& client_bytes, bool& sp, bool& sdr
+               , std::string ct, callback_type const & cb)
+      : bytes_left_(cl)
+      , buf_(buf)
+      , map_(m)
+      , client_bytes_left_(client_bytes)
+      , stdin_parsed_flag_(sp)
+      , stdin_data_read_(sdr)
+      , offset_(0)
+      , content_type_(ct)
+      //, client_(c)
+      , callback_(cb)
     {
 
     }
+    */
+
+    mutable_buffers_type prepare(std::size_t size)
+    {
+      std::size_t bufsz(impl_.buf_.size());
+      impl_.buf_.resize(bufsz + size);
+      return boost::asio::buffer(&impl_.buf_[bufsz], size);
+    }
+      
+    std::string buffer_string()
+    {
+      return std::string(impl_.buf_.begin() + offset_, impl_.buf_.end());
+    }
     
+    boost::system::error_code 
+      parse(boost::system::error_code& ec)
+    {
+      parse_boundary_marker(ec);
+      //parse_one_form_part(impl, ec);
+      
+      move_to_start_of_first_part(ec);
+      
+      if (ec == boost::asio::error::eof) {
+        return boost::system::error_code();
+      }else
+      if (ec)
+        return ec;
+
+      do {
+        parse_form_part(ec);
+      }while( !impl_.stdin_parsed_
+           && impl_.client_.bytes_left() != 0
+           );//&& ec != boost::asio::error::eof );
+
+      return ec;
+    }
+
+    boost::system::error_code
+      parse_form_part(boost::system::error_code& ec)
+    {
+      if (!parse_form_part_meta_data(ec)
+      &&  !parse_form_part_data(ec))
+        return ec;
+
+      return ec;
+    }
+
+    boost::system::error_code
+      parse_form_part_data(boost::system::error_code& ec)
+    {
+      std::string regex("^(.*?)" // the data
+                        "\\x0D\\x0A" // CR LF
+                        "--" "(");
+      if (boundary_markers.size() > 1)
+      {
+        std::list<std::string>::iterator i(boundary_markers.begin());
+        regex = regex + "(?:" + *i + ")";
+        ++i;
+        for(; i != boundary_markers.end(); ++i)
+        {
+          regex = regex + "|(?:" + *i + ")";
+        }
+      }
+      else
+      {
+        regex += *boundary_markers.begin();
+      }
+      
+      regex += ")(--)?[ ]*\\x0D\\x0A";
+      boost::regex re(regex);
+      
+      typedef buffer_type::iterator buffer_iter;
+
+      boost::match_results<buffer_iter> matches;
+
+      std::size_t offset = offset_;
+
+      //int runs = 0;
+      buffer_iter begin(impl_.buf_.begin() + offset);
+      buffer_iter end(impl_.buf_.end());
+
+      for(;;)
+      {
+        if (!boost::regex_search(begin, end, matches, re
+                                , boost::match_default
+                                | boost::match_partial))
+        {
+          return boost::system::error_code(345, boost::system::system_category);
+        }
+        else
+        {
+          if (matches[1].matched)
+          {
+            form_parts_.back().buffer_
+             // = boost::range_iterator<;
+             = std::make_pair(matches[1].first, matches[1].second);
+            impl_.post_vars_[form_parts_.back().name] = matches[1];
+            offset_ = offset + matches[0].length();
+            pos_ = matches[0].second;
+
+            if (matches[3].matched)
+              impl_.stdin_parsed_ = true;
+            return ec;
+          }
+          else
+          {
+            std::size_t bytes_read = impl_.client_.read_some(prepare(64), ec);
+            
+            if (bytes_read == 0)
+            {
+              stdin_data_read_ = true;
+              return ec;
+            }
+
+            begin = impl_.buf_.begin() + offset;
+            end = impl_.buf_.end();
+
+            if (ec)
+              return ec;
+          }
+        }
+      }
+
+      return ec;
+    }
+
+    boost::system::error_code
+      parse_form_part_meta_data(boost::system::error_code& ec)
+    {
+      // Oh dear this is ugly. The move to Boost.Spirit will have to be sooner than planned.
+      // (it's a nested, recursive pattern, which regexes don't suit, apparently)
+      boost::regex re(  "(?:"         // [IGNORE] the line may be empty, as meta-data is optional
+                          "^"
+                          "([-\\w]+)" // name
+                          ":[ ^]*"       // separator
+                          "([-/\\w]+)" // optional(?) value
+                          ""
+                          "(?:"
+                            ";"
+                            "[ ]*"    // additional name/value pairs (don't capture)
+                            "([-\\w]+)" // name
+                            "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
+                            "(?:\"?([-.\\w]*)\"?)" // value may be empty
+                          ")?"
+                          "(?:"
+                            ";"
+                            "[ ]*"    // additional name/value pairs (don't capture)
+                            "([-\\w]+)" // name
+                            "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
+                            "(?:\"?([-.\\w]*)\"?)" // value may be empty
+                          ")?"        // mark the extra n/v pairs optional
+                          "\\x0D\\x0A"
+                        ")"
+                        "(?:"
+                          "([-\\w]+)" // name
+                          ":[ ^]*"       // separator
+                          "([-/\\w]+)" // optional(?) value
+                          ""
+                          "(?:"
+                            ";"
+                            "[ ]*"    // additional name/value pairs (don't capture)
+                            "([-\\w]+)" // name
+                            "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
+                            "(?:\"?([-.\\w]*)\"?)" // value may be empty
+                          ")?"
+                          "(?:"
+                            ";"
+                            "[ ]*"    // additional name/value pairs (don't capture)
+                            "([-\\w]+)" // name
+                            "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
+                            "(?:\"?([-.\\w]*)\"?)" // value may be empty
+                          ")?"        // mark the extra n/v pairs optional
+                          "\\x0D\\x0A"    // followed by the end of the line
+                        ")?" 
+                      "(\\x0D\\x0A)");     // followed by the 'header termination' line
+
+      typedef buffer_type::iterator buffer_iter;
+
+      boost::match_results<buffer_iter> matches;
+
+      std::size_t offset = offset_;
+      pos_ = impl_.buf_.begin();
+      int runs = 0;
+
+      std::size_t bytes_read = 0;
+      for(;;)
+      {
+        buffer_iter begin(impl_.buf_.begin() + offset);
+        buffer_iter end(impl_.buf_.end());
+        
+        if (!boost::regex_search(begin, end, matches, re
+                                , boost::match_default | boost::match_partial))
+        {
+          impl_.stdin_parsed_ = true;
+          return ec;
+        }
+        if (matches[0].matched)
+        {
+          common::form_part part;
+          for ( unsigned int i = 1
+              ; i < matches.size() 
+               && matches[i].matched
+               && !matches[i].str().empty()
+              ; i+=2)
+          {
+            if (matches[i].str() == "name")
+            {
+              part.name = matches[i+1];
+            }
+            else
+            {
+              part.meta_data_[matches[i]]
+                = std::make_pair(matches[i+1].first, matches[i+1].second);
+            }
+            form_parts_.push_back(part);
+         }
+          
+         if (matches[13].str() == "\r\n")
+         {
+           offset_ = offset + matches[0].length();
+           offset += matches[0].length();
+           pos_ = matches[0].second;
+          
+           return ec;
+         }
+         else
+         {
+           throw std::runtime_error("Invalid POST data (header wasn't terminated as expected)");
+         }
+         
+        }else{
+          bytes_read = impl_.client_.read_some(prepare(64), ec);
+          if (ec)
+            return ec;
+          if (++runs > 40)
+          {
+            std::cerr<< "Done 40 runs; bailing out" << std::endl;
+            break;
+          }
+       }
+      }
+
+      return ec;
+    }
+
+    boost::system::error_code
+      move_to_start_of_first_part(boost::system::error_code& ec)
+    {
+      boost::regex re("((?:.*)?"   // optional leading characters
+                      //"(?:\\x0D\\x0A)|^" // start of line
+                      "[\\x0D\\x0A^]*?"
+                      "("
+                        "--" + boundary_markers.front() + // two dashes and our marker
+                      ")"
+                      "(--)?" // optional two dashes (not sure if this is allowed)
+                      " *\\x0D\\x0A)");
+                                        // on the first marker.
+
+      typedef buffer_type::iterator buffer_iter;
+      //std::cerr<< "Regex := " << re << std::endl;
+
+      boost::match_results<buffer_iter> matches;
+
+      // get data into our buffer until we reach the first boundary marker.
+      int runs = 0;
+      std::size_t offset = 0;
+      std::size_t bytes_read = 0;
+      for(;;)
+      {
+        bytes_read = impl_.client_.read_some(prepare(32), ec);
+        if (ec || (bytes_read == 0))
+          return ec;
+        buffer_iter begin(impl_.buf_.begin());// + offset);
+        buffer_iter end(impl_.buf_.end());
+        if (!boost::regex_search(begin, end //impl.buf_.begin(), impl.buf_.end()
+                                , matches, re, boost::match_default | boost::match_partial))
+        {
+          offset = impl_.buf_.size();
+          continue;
+        }
+        else
+        {
+          if (matches[2].matched)
+          {
+            impl_.buf_.erase(impl_.buf_.begin(), matches[0].second);
+            offset_ = 0;
+            pos_ = impl_.buf_.begin();
+            return ec;
+          }
+          else
+          {
+            if (++runs > 10)
+              return ec;
+            continue;
+          }
+        }
+      }
+      // skip that line and then erase the buffer
+      return ec;
+    }
+
+    boost::system::error_code
+      parse_one_form_part(boost::system::error_code& ec)
+    {
+      // continuously read data while parsing it until one complete form part has
+      // been read.
+      // Note, this may mean recursing into embedded sub-parts if necessary, but
+      // still only the first *complete* part/sub-part would be read.
+      //boost::regex re("\r\n--" + boundary_marker + " +
+
+      for(;;)
+      {
+        //if (impl.client_->read_some(impl.prepare(1024), ec))
+        //  return ec;
+        //boost::asio::read_until(impl.client_-> impl.buffer_, boundary_marker, ec);
+        break;
+
+
+      }
+
+      return ec;
+    }
+
+    /// Get the boundary marker from the CONTENT_TYPE header.
+    boost::system::error_code
+      parse_boundary_marker(boost::system::error_code& ec)
+    {
+      // get the meta-data appended to the content_type
+      std::string content_type_(impl_.env_vars_["CONTENT_TYPE"]);
+      //BOOST_ASSERT(!content_type.empty());
+
+      boost::regex re("; ?boundary=\"?([^\"\n\r]+)\"?");
+      boost::smatch match_results;
+      if (!boost::regex_search(content_type_, match_results, re))
+        return boost::system::error_code(666, boost::system::system_category);
+
+      boundary_marker = match_results[1].str();
+      // New boundary markers are added to the front of the list.
+      boundary_markers.push_front(match_results[1].str());
+
+      return ec;
+    }
+
   private:
-    std::set<std::string> boundary_markers_;
-    std::vector<common::form_part> form_parts_;
+    //std::set<std::string> boundary_markers_;
+    //std::vector<common::form_part> form_parts_;
 
     //buffer_type& buffer_;
 
-    callback_type callback_;
+    //callback_type callback_;
   };
 
  } // namespace detail
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/stdio.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -60,11 +60,11 @@
     std::size_t read_some(MutableBufferSequence buf
                          , boost::system::error_code& ec)
     {
-      if (std::cin.eof())
-      {
+      //if (std::cin.eof())
+      //{
         //ec = boost::asio::error::eof;
-        return boost::asio::error::eof;
-      }
+      //  return boost::asio::error::eof;
+      //}
       //if( buf.data() != in_.rdbuf() )
       //  return in_.read(buf.begin(), buf.size());
       //return buf.size();
@@ -81,29 +81,27 @@
         ec = boost::system::error_code(654, boost::system::system_category);
         return 0;
       }
-      //std::cerr<< "Read data" << std::endl
-      //         << "after = {" << std::endl
+      */
+      //std::cerr<< "before = {" << std::endl
       //         << std::string(boost::asio::buffer_cast<char *>(buf), boost::asio::buffer_size(buf)) << std::endl
       //         << "}" << std::endl;
-      return std::cin.gcount();
-      */
-      if (!std::fgets(boost::asio::buffer_cast<char *>(buf)
-                     , boost::asio::buffer_size(buf)
-                     , stdin))
+      
+      if (std::fread(boost::asio::buffer_cast<void *>(buf)
+                    , boost::asio::buffer_size(buf)
+                    , 1, stdin))
       {
-        return ::cgi::error::bad_read;
+        return strlen(boost::asio::buffer_cast<char *>(buf));
       }
-      int len( strlen(boost::asio::buffer_cast<char *>(buf)) );
-      // Not sure what to do about EOF yet.
-      //if (len < boost::asio::buffer_size(buf))
-      //{
-      //  return ::cgi::error::eof;
-      //}
-      std::cerr<< "Read data" << std::endl
-               << "after = {" << std::endl
-               << std::string(boost::asio::buffer_cast<char *>(buf), boost::asio::buffer_size(buf)) << std::endl
-               << "}" << std::endl;
-      return len;
+
+      if (std::feof(stdin))
+        ec = boost::asio::error::eof;
+      else
+      if (std::ferror(stdin))
+        ec = ::cgi::error::bad_read;
+      else
+        ec = ::cgi::error::broken_pipe;
+
+      return 0;
     }
 
     template<typename ConstBufferSequence>
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -50,105 +50,28 @@
     struct implementation_type
       : RequestImplType
     {
-      typedef boost::asio::const_buffers_1          const_buffers_type;
-      typedef boost::asio::mutable_buffers_1        mutable_buffers_type;
-      typedef typename RequestImplType::client_type client_type;
-      typedef std::vector<char>                     buffer_type;
-      //typedef std::list<std::string>::iterator      marker_list_type;
+      typedef boost::asio::const_buffers_1             const_buffers_type;
+      typedef boost::asio::mutable_buffers_1           mutable_buffers_type;
+      typedef typename RequestImplType::client_type    client_type;
+      typedef std::vector<char>                        buffer_type;
+      typedef detail::form_parser<implementation_type> form_parser_type;
 
       implementation_type()
-        : //buffer_()
-        //, istream_(&buffer_)
-          pos_()
-        , offset_(0)
-        , fp_(NULL)
+        : fp_(NULL)
       {
       }
 
       client_type client_;
 
-      std::string boundary_marker;
-      std::list<std::string> boundary_markers;
-      //std::vector<char> data_buffer_;
       // The number of characters left to read (ie. "content_length - bytes_read")
       std::size_t characters_left_;
       
-      //std::vector<char>::iterator read_pos_;
-      //boost::asio::streambuf buffer_;
-      //std::istream istream_;
-
       buffer_type buf_;
-      typename buffer_type::iterator pos_;
-      std::size_t offset_;
-      //boost::sub_match<typename buffer_type::iterator> offset_;
+
       std::vector<common::form_part> form_parts_;
       
-      detail::form_parser* fp_;
-
-      /*
-      mutable_buffers_type prepare(typename buffer_type::iterator& pos, std::size_t size)
-      {
-        std::size_t bufsz( buf_.size() );
-
-        // Reserve more space if it's needed.
-        // (this could be safer, referencing this against CONTENT_LENGTH)
-        if ( (bufsz + size) >= buf_.capacity() )
-        {
-          buf_.resize(bufsz + size);
-        }
-
-        return boost::asio::buffer(&(buf_.begin()), size);
-  //      return boost::asio::buffer(&buf_[bufsz], size);
-      }
-      */
-
-      mutable_buffers_type prepare(std::size_t size)
-      {
-        
-        std::size_t bufsz( buf_.size() );
-        //cerr<< "bufsz    = " << bufsz << endl;
-
-        // Reserve more space if it's needed.
-        // (this could be safer, referencing this against CONTENT_LENGTH)
-        //if ( (bufsz + size) >= buf_.capacity() )
-        //{
-          buf_.resize(bufsz + size);
-        //}
-
-        //cerr<< "Pre-read buffer (size: " << buf_.size() 
-         //   << "|capacity: " << buf_.capacity() << ") == {" << endl
-        //    << std::string(buf_.begin() + offset_, buf_.end()) << endl
-   //         << "-----end buffer-----" << endl
-   //         << "-------buffer-------" << endl
-  //          << std::string(&buf_[0], &buf_[buf_.size()]) << endl
-        //    << "}" << endl;
-            ;
-        //return boost::asio::buffer(&(*(buf_.end())), size);
-  //      return boost::asio::buffer(&(*(buf_.begin())) + bufsz, size);
-        return boost::asio::buffer(&buf_[bufsz], size);
-      }
-
-      std::string buffer_string()
-      {
-        return std::string(buf_.begin() + offset_, buf_.end());
-        //return std::string(pos_, buf_.size());//buf_.end());
-      }
-      /*
-        // Silently ignore a request to grow the buffer greater than the
-        // content-length allows.
-        // Note: this will break if the contents of the buffer are ever changed
-        // (such as if data is url-decoded and inserted back into the buffer).
-        if (size >= characters_left_)
-        {
-          size = characters_left_;
-        }
+      boost::scoped_ptr<form_parser_type> fp_;
 
-        data_buffer_.reserve(bufsz + size);
-        return boost::asio::buffer(data_buffer_.begin() + bufsz
-                                  , data_buffer_.capacity() - bufsz);
-      }
-      */
-      //boost::acgi::form_entry form_;
     };
 
     /// Return if the request is still open
@@ -419,39 +342,57 @@
       parse_url_encoded_form(implementation_type& impl
                             , boost::system::error_code& ec)
     {      
-      std::istream& is(std::cin);
-      char ch;
       std::string name;
       std::string str;
       map_type& post_map(impl.post_vars());
-
-      while( is.get(ch) && impl.characters_left_-- )
+      
+      char ch;
+      char ch1;
+      while( impl.characters_left_ )
       {
-          //std::cerr<< "; ch=" << ch << "; ";
-          switch(ch)
+        ch = getchar();
+        --impl.characters_left_;
+
+        switch(ch)
+        {
+        case '%': // unencode a hex character sequence
+          if (impl.characters_left_ >= 2)
           {
-          case '%': // unencode a hex character sequence
-              // note: function params are resolved in an undefined order!
-              str += detail::url_decode(is);
-              impl.characters_left_ -= 2; // this is dodgy **FIXME**
-              break;
-          case '+':
-              str.append(1, ' ');
-              break;
-          case ' ':
-              continue;
-          case '=': // the name is complete, now get the corresponding value
-              name = str;
-              str.clear();
-              break;
-          case '&': // we now have the name/value pair, so save it
-              post_map[name] = str;
-              str.clear();
-              name.clear();
-             break;
-          default:
-              str.append(1, ch);
+            ch = getchar();
+            ch1 = getchar();
+            if (std::isxdigit(ch) && std::isxdigit(ch1))
+            {
+              str.append(1, detail::hex_to_char(ch, ch1));
+            }
+            else // we don't have a hex sequence
+            {
+              str.append(1, '%').append(1, ch).append(1, ch1);
+            }
+            impl.characters_left_ -= 2;
+          }
+          else // There aren't enough characters to make a hex sequence
+          {
+            str.append(1, '%');
+            --impl.characters_left_;
           }
+          break;
+        case '+':
+            str.append(1, ' ');
+            break;
+        case ' ':
+            continue;
+        case '=': // the name is complete, now get the corresponding value
+            name = str;
+            str.clear();
+            break;
+        case '&': // we now have the name/value pair, so save it
+            post_map[name] = str;
+            str.clear();
+            name.clear();
+           break;
+        default:
+            str.append(1, ch);
+        }
       }
       // save the last param (it won't have a trailing &)
       if( !name.empty() )
@@ -465,6 +406,15 @@
     boost::system::error_code
       parse_multipart_form(implementation_type& impl, boost::system::error_code& ec)
     {
+      impl.fp_.reset
+      (
+        new typename implementation_type::form_parser_type
+                ( impl )
+      );
+      impl.fp_->parse(ec);
+      return ec;
+    }
+      /*
       parse_boundary_marker(impl, ec);
       //parse_one_form_part(impl, ec);
       move_to_start_of_first_part(impl, ec);
@@ -756,7 +706,7 @@
            //   << impl.buffer_string() << endl
              // << "} or {" << endl;
               //<< std::string(impl.pos_, ;
-          /*
+          / *
           for (unsigned int i = 0; i < matches.size(); ++i)
           {
             if (matches[i].length())
@@ -769,7 +719,7 @@
           cerr<< "-------buf------" << endl
               << std::string(begin, end) << endl
               << "----------------" << endl;
-          */
+          * /
           //offset = impl.buf_.end();
             if (++runs > 40)
             {
@@ -934,17 +884,17 @@
       // New boundary markers are added to the front of the list.
       impl.boundary_markers.push_front(match_results[1].str());
 
-      /*
+      / *
       cerr<< "full = " << content_type << endl
           << "full search string = " << match_results[0] << endl
           << "marker length = " << match_results[1].length() << endl
           << "marker = " << impl.boundary_marker << endl
           << "_[2] = " << match_results[2] << endl;
-          */
+          * /
      
       return ec;
     }
-
+*/
     /// Read and parse a single cgi POST meta variable (greedily)
     template<typename RequestImpl>
     boost::system::error_code
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -547,15 +547,15 @@
     // **FIXME**
     void handle_admin_request(implementation_type& impl)
     {
-      std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__ 
-        << " handle_admin_request()" << std::endl;
+      //std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__ 
+      //  << " handle_admin_request()" << std::endl;
     }
 
     // **FIXME**
     void handle_other_request_header(implementation_type& impl)
     {
-      std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__ 
-        << " handle_other_request_header()" << std::endl;
+      //std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__ 
+      //  << " handle_other_request_header()" << std::endl;
     }
 
     // **FIXME**    
@@ -575,8 +575,8 @@
         return ec;
       }
       try {
-        std::cerr<< "**FIXME** request aborted (id = " << id
-          << ") but request not notified." << std::endl;
+        //std::cerr<< "**FIXME** request aborted (id = " << id
+        //  << ") but request not notified." << std::endl;
         //impl.client_.connection_->requests_.at(id - 1)->abort();
       }catch(...){
         ec = error::abort_request_record_recieved_for_invalid_request;
@@ -725,8 +725,8 @@
       }else
       if (!state)
       { // The header is confusing; something's wrong. Abort.
-        std::cerr<< "Bad header received (this isn't implemented properly yet"
-            << std::endl;
+        //std::cerr<< "Bad header received (this isn't implemented properly yet"
+        //    << std::endl;
         return error::bad_header_type;
       }
       // else route (ie. state == boost::indeterminate)
Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/request_ostream.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/request_ostream.hpp	(original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/request_ostream.hpp	2008-03-31 23:29:41 EDT (Mon, 31 Mar 2008)
@@ -9,6 +9,11 @@
 #ifndef CGI_REQUEST_OSTREAM_HPP_INCLUDED__
 #define CGI_REQUEST_OSTREAM_HPP_INCLUDED__
 
+#if 0 
+
+// THIS FILE ISN'T USED!
+// **FIXME**
+ 
 /*********************************
 ISSUES:
 -------
@@ -358,4 +363,6 @@
 
 #include "boost/cgi/detail/pop_options.hpp"
 
+#endif 
+
 #endif // CGI_REQUEST_OSTREAM_HPP_INCLUDED__