Boost logo

Boost-Commit :

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__


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