Changeset 44571


Ignore:
Timestamp:
Apr 19, 2008, 1:05:37 PM (10 years ago)
Author:
Darren Garvey
Message:

Factoring form_parser body into an ipp file.

Location:
sandbox/SOC/2007/cgi/trunk/boost/cgi/common
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp

    r43979 r44571  
     1//                   -- form_parser.hpp --
     2//
     3//            Copyright (c) Darren Garvey 2007.
     4// Distributed under the Boost Software License, Version 1.0.
     5//    (See accompanying file LICENSE_1_0.txt or copy at
     6//          http://www.boost.org/LICENSE_1_0.txt)
     7//
     8////////////////////////////////////////////////////////////////
    19#ifndef CGI_DETAIL_FORM_PARSER_HPP_INCLUDED__
    210#define CGI_DETAIL_FORM_PARSER_HPP_INCLUDED__
     
    3745    typedef RequestImplType     implementation_type;
    3846
    39     implementation_type& impl_;
    40     std::size_t& bytes_left_;
    41     buffer_type::iterator pos_;
    42     bool& stdin_data_read_;
    43     std::size_t offset_;
    44 
    45     std::string boundary_marker;
    46     std::list<std::string> boundary_markers;
    47     std::vector<common::form_part> form_parts_;
    48 
    49     form_parser(implementation_type& impl)
    50       : impl_(impl)
    51       , bytes_left_(impl.characters_left_)
    52       , stdin_data_read_(impl.stdin_data_read_)
    53       , offset_(0)
    54     {
    55     }
    56     /*
    57     form_parser(std::size_t& cl, buffer_type& buf, map_type& m
    58                , unsigned int& client_bytes, bool& sp, bool& sdr
    59                , std::string ct, callback_type const & cb)
    60       : bytes_left_(cl)
    61       , buf_(buf)
    62       , map_(m)
    63       , client_bytes_left_(client_bytes)
    64       , stdin_parsed_flag_(sp)
    65       , stdin_data_read_(sdr)
    66       , offset_(0)
    67       , content_type_(ct)
    68       //, client_(c)
    69       , callback_(cb)
    70     {
    71 
    72     }
    73     */
     47    form_parser(implementation_type& impl);
    7448
    7549    mutable_buffers_type prepare(std::size_t size)
     
    8660   
    8761    boost::system::error_code
    88       parse(boost::system::error_code& ec)
    89     {
    90       parse_boundary_marker(ec);
    91       //parse_one_form_part(impl, ec);
    92      
    93       move_to_start_of_first_part(ec);
    94      
    95       if (ec == boost::asio::error::eof) {
    96         return boost::system::error_code();
    97       }else
    98       if (ec)
    99         return ec;
    100 
    101       do {
    102         parse_form_part(ec);
    103       }while( !impl_.stdin_parsed_
    104            && impl_.client_.bytes_left() != 0
    105            );//&& ec != boost::asio::error::eof );
    106 
    107       return ec;
    108     }
     62      parse(boost::system::error_code& ec);
    10963
    11064    boost::system::error_code
    111       parse_form_part(boost::system::error_code& ec)
    112     {
    113       if (!parse_form_part_meta_data(ec)
    114       &&  !parse_form_part_data(ec))
    115         return ec;
    116 
    117       return ec;
    118     }
     65      parse_url_encoded_form(boost::system::error_code& ec);
    11966
    12067    boost::system::error_code
    121       parse_form_part_data(boost::system::error_code& ec)
    122     {
    123       std::string regex("^(.*?)" // the data
    124                         "\\x0D\\x0A" // CR LF
    125                         "--" "(");
    126       if (boundary_markers.size() > 1)
    127       {
    128         std::list<std::string>::iterator i(boundary_markers.begin());
    129         regex = regex + "(?:" + *i + ")";
    130         ++i;
    131         for(; i != boundary_markers.end(); ++i)
    132         {
    133           regex = regex + "|(?:" + *i + ")";
    134         }
    135       }
    136       else
    137       {
    138         regex += *boundary_markers.begin();
    139       }
    140      
    141       regex += ")(--)?[ ]*\\x0D\\x0A";
    142       boost::regex re(regex);
    143      
    144       typedef buffer_type::iterator buffer_iter;
    145 
    146       boost::match_results<buffer_iter> matches;
    147 
    148       std::size_t offset = offset_;
    149 
    150       //int runs = 0;
    151       buffer_iter begin(impl_.buf_.begin() + offset);
    152       buffer_iter end(impl_.buf_.end());
    153 
    154       for(;;)
    155       {
    156         if (!boost::regex_search(begin, end, matches, re
    157                                 , boost::match_default
    158                                 | boost::match_partial))
    159         {
    160           return boost::system::error_code(345, boost::system::system_category);
    161         }
    162         else
    163         {
    164           if (matches[1].matched)
    165           {
    166             form_parts_.back().buffer_
    167              // = boost::range_iterator<;
    168              = std::make_pair(matches[1].first, matches[1].second);
    169             impl_.post_vars_[form_parts_.back().name] = matches[1];
    170             offset_ = offset + matches[0].length();
    171             pos_ = matches[0].second;
    172 
    173             if (matches[3].matched)
    174               impl_.stdin_parsed_ = true;
    175             return ec;
    176           }
    177           else
    178           {
    179             std::size_t bytes_read = impl_.client_.read_some(prepare(64), ec);
    180            
    181             if (bytes_read == 0)
    182             {
    183               stdin_data_read_ = true;
    184               return ec;
    185             }
    186 
    187             begin = impl_.buf_.begin() + offset;
    188             end = impl_.buf_.end();
    189 
    190             if (ec)
    191               return ec;
    192           }
    193         }
    194       }
    195 
    196       return ec;
    197     }
     68      parse_multipart_form(boost::system::error_code& ec);
    19869
    19970    boost::system::error_code
    200       parse_form_part_meta_data(boost::system::error_code& ec)
    201     {
    202       // Oh dear this is ugly. The move to Boost.Spirit will have to be sooner than planned.
    203       // (it's a nested, recursive pattern, which regexes don't suit, apparently)
    204       boost::regex re(  "(?:"         // [IGNORE] the line may be empty, as meta-data is optional
    205                           "^"
    206                           "([-\\w]+)" // name
    207                           ":[ ^]*"       // separator
    208                           "([-/\\w]+)" // optional(?) value
    209                           ""
    210                           "(?:"
    211                             ";"
    212                             "[ ]*"    // additional name/value pairs (don't capture)
    213                             "([-\\w]+)" // name
    214                             "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
    215                             "(?:\"?([-.\\w]*)\"?)" // value may be empty
    216                           ")?"
    217                           "(?:"
    218                             ";"
    219                             "[ ]*"    // additional name/value pairs (don't capture)
    220                             "([-\\w]+)" // name
    221                             "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
    222                             "(?:\"?([-.\\w]*)\"?)" // value may be empty
    223                           ")?"        // mark the extra n/v pairs optional
    224                           "\\x0D\\x0A"
    225                         ")"
    226                         "(?:"
    227                           "([-\\w]+)" // name
    228                           ":[ ^]*"       // separator
    229                           "([-/\\w]+)" // optional(?) value
    230                           ""
    231                           "(?:"
    232                             ";"
    233                             "[ ]*"    // additional name/value pairs (don't capture)
    234                             "([-\\w]+)" // name
    235                             "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
    236                             "(?:\"?([-.\\w]*)\"?)" // value may be empty
    237                           ")?"
    238                           "(?:"
    239                             ";"
    240                             "[ ]*"    // additional name/value pairs (don't capture)
    241                             "([-\\w]+)" // name
    242                             "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*"       // separator
    243                             "(?:\"?([-.\\w]*)\"?)" // value may be empty
    244                           ")?"        // mark the extra n/v pairs optional
    245                           "\\x0D\\x0A"    // followed by the end of the line
    246                         ")?"
    247                       "(\\x0D\\x0A)");     // followed by the 'header termination' line
    248 
    249       typedef buffer_type::iterator buffer_iter;
    250 
    251       boost::match_results<buffer_iter> matches;
    252 
    253       std::size_t offset = offset_;
    254       pos_ = impl_.buf_.begin();
    255       int runs = 0;
    256 
    257       std::size_t bytes_read = 0;
    258       for(;;)
    259       {
    260         buffer_iter begin(impl_.buf_.begin() + offset);
    261         buffer_iter end(impl_.buf_.end());
    262        
    263         if (!boost::regex_search(begin, end, matches, re
    264                                 , boost::match_default | boost::match_partial))
    265         {
    266           impl_.stdin_parsed_ = true;
    267           return ec;
    268         }
    269         if (matches[0].matched)
    270         {
    271           common::form_part part;
    272           for ( unsigned int i = 1
    273               ; i < matches.size()
    274                && matches[i].matched
    275                && !matches[i].str().empty()
    276               ; i+=2)
    277           {
    278             if (matches[i].str() == "name")
    279             {
    280               part.name = matches[i+1];
    281             }
    282             else
    283             {
    284               part.meta_data_[matches[i]]
    285                 = std::make_pair(matches[i+1].first, matches[i+1].second);
    286             }
    287             form_parts_.push_back(part);
    288          }
    289          
    290          if (matches[13].str() == "\r\n")
    291          {
    292            offset_ = offset + matches[0].length();
    293            offset += matches[0].length();
    294            pos_ = matches[0].second;
    295          
    296            return ec;
    297          }
    298          else
    299          {
    300            throw std::runtime_error("Invalid POST data (header wasn't terminated as expected)");
    301          }
    302          
    303         }else{
    304           bytes_read = impl_.client_.read_some(prepare(64), ec);
    305           if (ec)
    306             return ec;
    307           if (++runs > 40)
    308           {
    309             std::cerr<< "Done 40 runs; bailing out" << std::endl;
    310             break;
    311           }
    312        }
    313       }
    314 
    315       return ec;
    316     }
     71      parse_form_part(boost::system::error_code& ec);
    31772
    31873    boost::system::error_code
    319       move_to_start_of_first_part(boost::system::error_code& ec)
    320     {
    321       boost::regex re("((?:.*)?"   // optional leading characters
    322                       //"(?:\\x0D\\x0A)|^" // start of line
    323                       "[\\x0D\\x0A^]*?"
    324                       "("
    325                         "--" + boundary_markers.front() + // two dashes and our marker
    326                       ")"
    327                       "(--)?" // optional two dashes (not sure if this is allowed)
    328                       " *\\x0D\\x0A)");
    329                                         // on the first marker.
    330 
    331       typedef buffer_type::iterator buffer_iter;
    332       //std::cerr<< "Regex := " << re << std::endl;
    333 
    334       boost::match_results<buffer_iter> matches;
    335 
    336       // get data into our buffer until we reach the first boundary marker.
    337       int runs = 0;
    338       std::size_t offset = 0;
    339       std::size_t bytes_read = 0;
    340       for(;;)
    341       {
    342         bytes_read = impl_.client_.read_some(prepare(32), ec);
    343         if (ec || (bytes_read == 0))
    344           return ec;
    345         buffer_iter begin(impl_.buf_.begin());// + offset);
    346         buffer_iter end(impl_.buf_.end());
    347         if (!boost::regex_search(begin, end //impl.buf_.begin(), impl.buf_.end()
    348                                 , matches, re, boost::match_default | boost::match_partial))
    349         {
    350           offset = impl_.buf_.size();
    351           continue;
    352         }
    353         else
    354         {
    355           if (matches[2].matched)
    356           {
    357             impl_.buf_.erase(impl_.buf_.begin(), matches[0].second);
    358             offset_ = 0;
    359             pos_ = impl_.buf_.begin();
    360             return ec;
    361           }
    362           else
    363           {
    364             if (++runs > 10)
    365               return ec;
    366             continue;
    367           }
    368         }
    369       }
    370       // skip that line and then erase the buffer
    371       return ec;
    372     }
     74      parse_form_part_data(boost::system::error_code& ec);
    37375
    37476    boost::system::error_code
    375       parse_one_form_part(boost::system::error_code& ec)
    376     {
    377       // continuously read data while parsing it until one complete form part has
    378       // been read.
    379       // Note, this may mean recursing into embedded sub-parts if necessary, but
    380       // still only the first *complete* part/sub-part would be read.
    381       //boost::regex re("\r\n--" + boundary_marker + " +
     77      parse_form_part_meta_data(boost::system::error_code& ec);
    38278
    383       for(;;)
    384       {
    385         //if (impl.client_->read_some(impl.prepare(1024), ec))
    386         //  return ec;
    387         //boost::asio::read_until(impl.client_-> impl.buffer_, boundary_marker, ec);
    388         break;
    389 
    390 
    391       }
    392 
    393       return ec;
    394     }
     79    boost::system::error_code
     80      move_to_start_of_first_part(boost::system::error_code& ec);
    39581
    39682    /// Get the boundary marker from the CONTENT_TYPE header.
    39783    boost::system::error_code
    398       parse_boundary_marker(boost::system::error_code& ec)
    399     {
    400       // get the meta-data appended to the content_type
    401       std::string content_type_(impl_.env_vars_["CONTENT_TYPE"]);
    402       //BOOST_ASSERT(!content_type.empty());
    403 
    404       boost::regex re("; ?boundary=\"?([^\"\n\r]+)\"?");
    405       boost::smatch match_results;
    406       if (!boost::regex_search(content_type_, match_results, re))
    407         return boost::system::error_code(666, boost::system::system_category);
    408 
    409       boundary_marker = match_results[1].str();
    410       // New boundary markers are added to the front of the list.
    411       boundary_markers.push_front(match_results[1].str());
    412 
    413       return ec;
    414     }
     84      parse_boundary_marker(boost::system::error_code& ec);
    41585
    41686  private:
    417     //std::set<std::string> boundary_markers_;
    418     //std::vector<common::form_part> form_parts_;
     87    implementation_type& impl_;
     88    std::size_t& bytes_left_;
     89    buffer_type::iterator pos_;
     90    //bool& stdin_data_read_;
     91    std::size_t offset_;
    41992
    420     //buffer_type& buffer_;
     93    std::string boundary_marker;
     94    std::list<std::string> boundary_markers;
     95    std::vector<common::form_part> form_parts_;
    42196
    42297    //callback_type callback_;
     
    426101} // namespace cgi
    427102
     103#include "boost/cgi/common/form_parser.ipp"
     104
    428105#endif // CGI_DETAIL_FORM_PARSER_HPP_INCLUDED__
    429106
Note: See TracChangeset for help on using the changeset viewer.