Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| SHA1 Hash: | 67e91438e664cd39afc8ed818f62a62dc68039f7 |
|---|---|
| Date: | 2008-09-18 14:56:40 |
| User: | stephan |
| Comment: | added unescaping of %XX sequences in GET parameter values |
Tags And Properties
- branch=trunk inherited from [d45e7467f2]
- sym-trunk inherited from [d45e7467f2]
Changes
Changes to parsepp_url.hpp
| Old (541b0345e82133a7) | New (68112ef8f8acc8d9) | |||
|---|---|---|---|---|
| 1 | #ifndef S11N_NET_PARSEPP_URL_H_INCLUDED | 1 | #ifndef S11N_NET_PARSEPP_URL_H_INCLUDED | |
| 2 | #define S11N_NET_PARSEPP_URL_H_INCLUDED 1 | 2 | #define S11N_NET_PARSEPP_URL_H_INCLUDED 1 | |
| 3 | 3 | |||
| 4 | #include "parsepp.hpp" | 4 | #include "parsepp.hpp" | |
| 5 | #include <map> | 5 | #include <map> | |
| 6 | #include <string> | 6 | #include <string> | |
| > | 7 | #include <sstream> | ||
| 7 | 8 | |||
| 8 | namespace Ps { | 9 | namespace Ps { | |
| 9 | 10 | |||
| 10 | /** | 11 | /** | |
| 11 | Ps::url encapsulates a parser for URLs. It does no escaping at all - that is | | | 12 | Ps::url encapsulates a parser for URLs. It unescaped %XX sequences in the |
| 12 | up to client code. | | | 13 | value parts of URL parameter values, but does no other unescaping. |
| | | 14 | |||
| | | 15 | For historical reasons, file:// URLs are handled a bit less strictly | ||
| | | 16 | than other URL schemes. The following are valid for this parser: | ||
| | | 17 | |||
| | | 18 | file:relative/path | ||
| | | 19 | |||
| | | 20 | file://relative/path | ||
| | | 21 | |||
| | | 22 | file:/absolute/path | ||
| | | 23 | |||
| | | 24 | file:///absolute/path | ||
| | | 25 | |||
| | | 26 | |||
| | | 27 | Aside from that, it handles normal URLs: | ||
| | | 28 | |||
| | | 29 | protocol://[user[:[password]]@]hostname/path?KVP | ||
| | | 30 | |||
| | | 31 | Where KVP are key/value pairs in the form KEY[=[VALUE]], separated | ||
| | | 32 | by a '&' character. The VALUE part of each pair gets unescaped, | ||
| | | 33 | such that %XX (where XX is a hexidecimal value of a character) get | ||
| | | 34 | transformed into their ASCII value (note that results are undefined | ||
| | | 35 | here with characters >127). | ||
| | | 36 | |||
| 13 | */ | 37 | */ | |
| 14 | namespace url { | 38 | namespace url { | |
| 15 | using namespace Ps; | 39 | using namespace Ps; | |
| 16 | #define RL rule_list | 40 | #define RL rule_list | |
| 17 | #define CL char_list | 41 | #define CL char_list | |
| 3 hidden lines | ||||
| 21 | struct url_state | 45 | struct url_state | |
| 22 | { | 46 | { | |
| 23 | typedef std::map<std::string,std::string> kvpmap; | 47 | typedef std::map<std::string,std::string> kvpmap; | |
| 24 | kvpmap params; // key/value pairs for GET params | 48 | kvpmap params; // key/value pairs for GET params | |
| 25 | kvpmap parts; // key/value pairs for various parts of URL | 49 | kvpmap parts; // key/value pairs for various parts of URL | |
| 26 | std::string key; // last-read key. | | | 50 | std::string key; // buffer for the last-read key. |
| 27 | void clear() | 51 | void clear() | |
| 28 | { | 52 | { | |
| 29 | this->params.clear(); | 53 | this->params.clear(); | |
| 30 | this->parts.clear(); | 54 | this->parts.clear(); | |
| 31 | this->key.clear(); | 55 | this->key.clear(); | |
| 10 hidden lines | ||||
| 42 | //COUT << "set_key: " << m << '\n'; | 66 | //COUT << "set_key: " << m << '\n'; | |
| 43 | s.params[s.key = m] = ""; // ensure an empty value in case the val field is empty. | 67 | s.params[s.key = m] = ""; // ensure an empty value in case the val field is empty. | |
| 44 | } | 68 | } | |
| 45 | }; | 69 | }; | |
| 46 | 70 | |||
| 47 | /** Action to set a value. Uses the last-read key as the lookup key. */ | | | 71 | |
| | | 72 | template <bool IsEsc> | ||
| | | 73 | struct a_esc_append | ||
| | | 74 | { | ||
| | | 75 | static void matched( Ps::parser_state &, const std::string & m, std::string & s ) | ||
| | | 76 | { | ||
| | | 77 | CERR << "a_esc_append<"<<IsEsc<<">:["<<m<<"]\n"; | ||
| | | 78 | if( IsEsc ) | ||
| | | 79 | { | ||
| | | 80 | std::istringstream is(m); | ||
| | | 81 | int x = '?'; | ||
| | | 82 | is >> std::hex >> x; // weird: reading directly into ch missing the std::hex handling | ||
| | | 83 | s.push_back(std::string::value_type(x)); | ||
| | | 84 | } | ||
| | | 85 | else | ||
| | | 86 | { | ||
| | | 87 | s += m; | ||
| | | 88 | } | ||
| | | 89 | } | ||
| | | 90 | }; | ||
| | | 91 | |||
| | | 92 | |||
| | | 93 | /** | ||
| | | 94 | Action to set a value. Uses the last-read key as the lookup key. | ||
| | | 95 | |||
| | | 96 | The value is automatically un-percent-escaped (e.g. %20 is converted | ||
| | | 97 | to a space). | ||
| | | 98 | */ | ||
| 48 | struct a_kvp_set_val | 99 | struct a_kvp_set_val | |
| 49 | { | 100 | { | |
| 50 | static void matched( Ps::parser_state &, const std::string & v, url_state & s ) | | | 101 | static void matched( Ps::parser_state &, const std::string & m, url_state & s ) |
| 51 | { | 102 | { | |
| 52 | //COUT << "set_val: " << s.key << '='<<v << '\n'; | | | 103 | COUT << "a_kvp_set_val: " << s.key << '='<<m << '\n'; |
| 53 | s.params[s.key] = v; | | | 104 | if( ! m.empty() ) |
| | | 105 | { | ||
| | | 106 | std::string unesc; | ||
| | | 107 | typedef r_ch<'%'> PCT; | ||
| | | 108 | typedef r_repeat<r_xdigit,2> DIGITS; | ||
| | | 109 | typedef r_and<RL<PCT,DIGITS> > ESC; | ||
| | | 110 | typedef r_and<RL<PCT, | ||
| | | 111 | r_action< DIGITS, a_esc_append<true> > | ||
| | | 112 | > > AESC; | ||
| | | 113 | typedef r_action< r_plus< r_and<RL<r_notat<ESC>,r_advance<1> > > >, a_esc_append<false> > NESC; | ||
| | | 114 | typedef r_plus< r_or< RL< AESC, NESC > > > START; | ||
| | | 115 | Ps::parser_state ps(m); | ||
| | | 116 | Ps::parse<START>(ps, unesc); | ||
| | | 117 | s.params[s.key] = unesc; | ||
| | | 118 | } | ||
| | | 119 | else | ||
| | | 120 | { | ||
| | | 121 | s.params[s.key] = m; | ||
| | | 122 | } | ||
| 54 | s.key = ""; | 123 | s.key = ""; | |
| 55 | } | 124 | } | |
| 56 | }; | 125 | }; | |
| 57 | 126 | |||
| 58 | /** | 127 | /** | |
| 206 hidden lines | ||||
| 265 | } | 334 | } | |
| 266 | 335 | |||
| 267 | }} // namespaces | 336 | }} // namespaces | |
| 268 | 337 | |||
| 269 | #endif // S11N_NET_PARSEPP_URL_H_INCLUDED | 338 | #endif // S11N_NET_PARSEPP_URL_H_INCLUDED | |