author | Michael Krelin <hacker@klever.net> | 2005-07-19 13:08:58 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2005-07-19 13:08:58 (UTC) |
commit | db69589bdc32c60b1fce6700a35d4126058bf7bc (patch) (unidiff) | |
tree | 34727675eaeb4210436a9b61119c7484dbc0cd97 /src | |
parent | 9cc67ea5af191d5bc1f26506c35d8387a05361c2 (diff) | |
download | kingate-db69589bdc32c60b1fce6700a35d4126058bf7bc.zip kingate-db69589bdc32c60b1fce6700a35d4126058bf7bc.tar.gz kingate-db69589bdc32c60b1fce6700a35d4126058bf7bc.tar.bz2 |
turned cookies into multimap
-rw-r--r-- | src/cookies.cc | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/src/cookies.cc b/src/cookies.cc index 40a0c8b..1ee4f7c 100644 --- a/src/cookies.cc +++ b/src/cookies.cc | |||
@@ -1,242 +1,245 @@ | |||
1 | #include "kingate/cookies.h" | 1 | #include "kingate/cookies.h" |
2 | #include "kingate/util.h" | 2 | #include "kingate/util.h" |
3 | #include "kingate/exception.h" | 3 | #include "kingate/exception.h" |
4 | 4 | ||
5 | namespace kingate { | 5 | namespace kingate { |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * RFC 2109: | 8 | * RFC 2109: |
9 | * av-pairs = av-pair *(";" av-pair) | 9 | * av-pairs = av-pair *(";" av-pair) |
10 | * av-pair = attr ["=" value] ; optional value | 10 | * av-pair = attr ["=" value] ; optional value |
11 | * attr = token | 11 | * attr = token |
12 | * value = word | 12 | * value = word |
13 | * word = token | quoted-string | 13 | * word = token | quoted-string |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /* RFC 2109: | 16 | /* RFC 2109: |
17 | * | 17 | * |
18 | * The origin server effectively ends a session by sending the client a | 18 | * The origin server effectively ends a session by sending the client a |
19 | * Set-Cookie header with Max-Age=0. | 19 | * Set-Cookie header with Max-Age=0. |
20 | * | 20 | * |
21 | * An origin server may include multiple Set-Cookie headers in a response. | 21 | * An origin server may include multiple Set-Cookie headers in a response. |
22 | * Note that an intervening gateway could fold multiple such headers into a | 22 | * Note that an intervening gateway could fold multiple such headers into a |
23 | * single header. | 23 | * single header. |
24 | * | 24 | * |
25 | * | 25 | * |
26 | * set-cookie = "Set-Cookie:" cookies | 26 | * set-cookie = "Set-Cookie:" cookies |
27 | * cookies = 1#cookie | 27 | * cookies = 1#cookie |
28 | * cookie = NAME "=" VALUE *(";" cookie-av) | 28 | * cookie = NAME "=" VALUE *(";" cookie-av) |
29 | * NAME = attr | 29 | * NAME = attr |
30 | * VALUE = value | 30 | * VALUE = value |
31 | * cookie-av = "Comment" "=" value | 31 | * cookie-av = "Comment" "=" value |
32 | * | "Domain" "=" value | 32 | * | "Domain" "=" value |
33 | * | "Max-Age" "=" value | 33 | * | "Max-Age" "=" value |
34 | * | "Path" "=" value | 34 | * | "Path" "=" value |
35 | * | "Secure" | 35 | * | "Secure" |
36 | * | "Version" "=" 1*DIGIT | 36 | * | "Version" "=" 1*DIGIT |
37 | * | 37 | * |
38 | * | 38 | * |
39 | * The origin server should send the following additional HTTP/1.1 | 39 | * The origin server should send the following additional HTTP/1.1 |
40 | * response headers, depending on circumstances: | 40 | * response headers, depending on circumstances: |
41 | * | 41 | * |
42 | * * To suppress caching of the Set-Cookie header: Cache-control: no- | 42 | * * To suppress caching of the Set-Cookie header: Cache-control: no- |
43 | * cache="set-cookie". | 43 | * cache="set-cookie". |
44 | * | 44 | * |
45 | * and one of the following: | 45 | * and one of the following: |
46 | * | 46 | * |
47 | * * To suppress caching of a private document in shared caches: Cache- | 47 | * * To suppress caching of a private document in shared caches: Cache- |
48 | * control: private. | 48 | * control: private. |
49 | * | 49 | * |
50 | * * To allow caching of a document and require that it be validated | 50 | * * To allow caching of a document and require that it be validated |
51 | * before returning it to the client: Cache-control: must-revalidate. | 51 | * before returning it to the client: Cache-control: must-revalidate. |
52 | * | 52 | * |
53 | * * To allow caching of a document, but to require that proxy caches | 53 | * * To allow caching of a document, but to require that proxy caches |
54 | * (not user agent caches) validate it before returning it to the | 54 | * (not user agent caches) validate it before returning it to the |
55 | * client: Cache-control: proxy-revalidate. | 55 | * client: Cache-control: proxy-revalidate. |
56 | * | 56 | * |
57 | * * To allow caching of a document and request that it be validated | 57 | * * To allow caching of a document and request that it be validated |
58 | * before returning it to the client (by "pre-expiring" it): | 58 | * before returning it to the client (by "pre-expiring" it): |
59 | * Cache-control: max-age=0. Not all caches will revalidate the | 59 | * Cache-control: max-age=0. Not all caches will revalidate the |
60 | * document in every case. | 60 | * document in every case. |
61 | * | 61 | * |
62 | * HTTP/1.1 servers must send Expires: old-date (where old-date is a | 62 | * HTTP/1.1 servers must send Expires: old-date (where old-date is a |
63 | * date long in the past) on responses containing Set-Cookie response | 63 | * date long in the past) on responses containing Set-Cookie response |
64 | * headers unless they know for certain (by out of band means) that | 64 | * headers unless they know for certain (by out of band means) that |
65 | * there are no downsteam HTTP/1.0 proxies. HTTP/1.1 servers may send | 65 | * there are no downsteam HTTP/1.0 proxies. HTTP/1.1 servers may send |
66 | * other Cache-Control directives that permit caching by HTTP/1.1 | 66 | * other Cache-Control directives that permit caching by HTTP/1.1 |
67 | * proxies in addition to the Expires: old-date directive; the Cache- | 67 | * proxies in addition to the Expires: old-date directive; the Cache- |
68 | * Control directive will override the Expires: old-date for HTTP/1.1 | 68 | * Control directive will override the Expires: old-date for HTTP/1.1 |
69 | * proxies. | 69 | * proxies. |
70 | * | 70 | * |
71 | */ | 71 | */ |
72 | 72 | ||
73 | void cookie::_set_string(const string& p,const string& v) { | 73 | void cookie::_set_string(const string& p,const string& v) { |
74 | (*this)[p]=v; | 74 | (*this)[p]=v; |
75 | } | 75 | } |
76 | 76 | ||
77 | void cookie::set_comment(const string& c) { | 77 | void cookie::set_comment(const string& c) { |
78 | _set_string("comment",c); | 78 | _set_string("comment",c); |
79 | } | 79 | } |
80 | void cookie::set_domain(const string& d) { | 80 | void cookie::set_domain(const string& d) { |
81 | _set_string("domain",d); | 81 | _set_string("domain",d); |
82 | } | 82 | } |
83 | void cookie::set_max_age(const string& ma) { | 83 | void cookie::set_max_age(const string& ma) { |
84 | _set_string("max-age",ma); | 84 | _set_string("max-age",ma); |
85 | } | 85 | } |
86 | void cookie::set_path(const string& p) { | 86 | void cookie::set_path(const string& p) { |
87 | _set_string("path",p); | 87 | _set_string("path",p); |
88 | } | 88 | } |
89 | void cookie::set_secure(bool s) { | 89 | void cookie::set_secure(bool s) { |
90 | if(s) | 90 | if(s) |
91 | _set_string("secure",""); | 91 | _set_string("secure",""); |
92 | else | 92 | else |
93 | erase("secure"); | 93 | erase("secure"); |
94 | } | 94 | } |
95 | 95 | ||
96 | void cookie::set_expires(const string& e) { | 96 | void cookie::set_expires(const string& e) { |
97 | (*this)["expires"] = e; | 97 | (*this)["expires"] = e; |
98 | } | 98 | } |
99 | 99 | ||
100 | const string& cookie::_get_string(const string& s) const { | 100 | const string& cookie::_get_string(const string& s) const { |
101 | const_iterator i = find(s); | 101 | const_iterator i = find(s); |
102 | if(i==end()) | 102 | if(i==end()) |
103 | throw exception_notfound(CODEPOINT,"No parameter set"); | 103 | throw exception_notfound(CODEPOINT,"No parameter set"); |
104 | return i->second; | 104 | return i->second; |
105 | } | 105 | } |
106 | 106 | ||
107 | const string& cookie::get_comment() const { | 107 | const string& cookie::get_comment() const { |
108 | return _get_string("comment"); | 108 | return _get_string("comment"); |
109 | } | 109 | } |
110 | const string& cookie::get_domain() const { | 110 | const string& cookie::get_domain() const { |
111 | return _get_string("domain"); | 111 | return _get_string("domain"); |
112 | } | 112 | } |
113 | const string& cookie::get_max_age() const { | 113 | const string& cookie::get_max_age() const { |
114 | return _get_string("max-age"); | 114 | return _get_string("max-age"); |
115 | } | 115 | } |
116 | const string& cookie::get_path() const { | 116 | const string& cookie::get_path() const { |
117 | return _get_string("path"); | 117 | return _get_string("path"); |
118 | } | 118 | } |
119 | bool cookie::get_secure() const { | 119 | bool cookie::get_secure() const { |
120 | return find("secure")!=end(); | 120 | return find("secure")!=end(); |
121 | } | 121 | } |
122 | 122 | ||
123 | const string& cookie::get_expires() const { | 123 | const string& cookie::get_expires() const { |
124 | return _get_string("expires"); | 124 | return _get_string("expires"); |
125 | } | 125 | } |
126 | 126 | ||
127 | bool cookie::has_comment() const { | 127 | bool cookie::has_comment() const { |
128 | return find("comment")!=end(); | 128 | return find("comment")!=end(); |
129 | } | 129 | } |
130 | bool cookie::has_domain() const { | 130 | bool cookie::has_domain() const { |
131 | return find("domain")!=end(); | 131 | return find("domain")!=end(); |
132 | } | 132 | } |
133 | bool cookie::has_max_age() const { | 133 | bool cookie::has_max_age() const { |
134 | return find("max-age")!=end(); | 134 | return find("max-age")!=end(); |
135 | } | 135 | } |
136 | bool cookie::has_path() const { | 136 | bool cookie::has_path() const { |
137 | return find("path")!=end(); | 137 | return find("path")!=end(); |
138 | } | 138 | } |
139 | 139 | ||
140 | bool cookie::has_expires() const { | 140 | bool cookie::has_expires() const { |
141 | return find("expires")!=end(); | 141 | return find("expires")!=end(); |
142 | } | 142 | } |
143 | 143 | ||
144 | void cookie::unset_comment() { | 144 | void cookie::unset_comment() { |
145 | erase("comment"); | 145 | erase("comment"); |
146 | } | 146 | } |
147 | void cookie::unset_domain() { | 147 | void cookie::unset_domain() { |
148 | erase("domain"); | 148 | erase("domain"); |
149 | } | 149 | } |
150 | void cookie::unset_max_age() { | 150 | void cookie::unset_max_age() { |
151 | erase("max-age"); | 151 | erase("max-age"); |
152 | } | 152 | } |
153 | void cookie::unset_path() { | 153 | void cookie::unset_path() { |
154 | erase("path"); | 154 | erase("path"); |
155 | } | 155 | } |
156 | 156 | ||
157 | void cookie::unset_expires() { | 157 | void cookie::unset_expires() { |
158 | erase("expires"); | 158 | erase("expires"); |
159 | } | 159 | } |
160 | 160 | ||
161 | string cookie::set_cookie_header_rfc2109() const { | 161 | string cookie::set_cookie_header_rfc2109() const { |
162 | string rv = name + "=" + http_quoted_string(value); | 162 | string rv = name + "=" + http_quoted_string(value); |
163 | for(const_iterator i=begin();i!=end();++i) { | 163 | for(const_iterator i=begin();i!=end();++i) { |
164 | if(i->first=="secure") { | 164 | if(i->first=="secure") { |
165 | rv += "; secure"; | 165 | rv += "; secure"; |
166 | }else{ | 166 | }else{ |
167 | rv += "; "+i->first+"="+http_quote(i->second); | 167 | rv += "; "+i->first+"="+http_quote(i->second); |
168 | } | 168 | } |
169 | } | 169 | } |
170 | rv += "; Version=1"; | 170 | rv += "; Version=1"; |
171 | return rv; | 171 | return rv; |
172 | } | 172 | } |
173 | 173 | ||
174 | string cookie::set_cookie_header() const { | 174 | string cookie::set_cookie_header() const { |
175 | string rv = name + "=" + value; | 175 | string rv = name + "=" + value; |
176 | for(const_iterator i=begin();i!=end();++i) { | 176 | for(const_iterator i=begin();i!=end();++i) { |
177 | if(i->first=="secure") { | 177 | if(i->first=="secure") { |
178 | rv += "; secure"; | 178 | rv += "; secure"; |
179 | }else{ | 179 | }else{ |
180 | rv += "; "+i->first+"="+i->second; | 180 | rv += "; "+i->first+"="+i->second; |
181 | } | 181 | } |
182 | } | 182 | } |
183 | return rv; | 183 | return rv; |
184 | } | 184 | } |
185 | 185 | ||
186 | void cookies_t::set_cookie(const cookie& c) { | ||
187 | insert(value_type(c.get_name(),c)); | ||
188 | } | ||
189 | |||
186 | bool cookies_t::has_cookie(const key_type& n) const { | 190 | bool cookies_t::has_cookie(const key_type& n) const { |
187 | return find(n)!=end(); | 191 | return find(n)!=end(); |
188 | } | 192 | } |
189 | 193 | ||
190 | const cookie& cookies_t::get_cookie(const key_type& n) const { | 194 | const cookie& cookies_t::get_cookie(const key_type& n) const { |
191 | const_iterator i=find(n); | 195 | const_iterator i=find(n); |
192 | if(i==end()) | 196 | if(i==end()) |
193 | throw exception_notfound(CODEPOINT,"No cookie with such name found"); | 197 | throw exception_notfound(CODEPOINT,"No cookie with such name found"); |
194 | return i->second; | 198 | return i->second; |
195 | } | 199 | } |
196 | 200 | ||
197 | cookie& cookies_t::get_cookie(const key_type& n) { | 201 | cookie& cookies_t::get_cookie(const key_type& n) { |
198 | iterator i=find(n); | 202 | iterator i=find(n); |
199 | if(i==end()) | 203 | if(i==end()) |
200 | throw exception_notfound(CODEPOINT,"No cookie with such name found"); | 204 | throw exception_notfound(CODEPOINT,"No cookie with such name found"); |
201 | return i->second; | 205 | return i->second; |
202 | } | 206 | } |
203 | 207 | ||
204 | void cookies_t::parse_cookies(const string& s) { | 208 | void cookies_t::parse_cookies(const string& s) { |
205 | string str = s; | 209 | string str = s; |
206 | while(!str.empty()) { | 210 | while(!str.empty()) { |
207 | string::size_type sc = str.find(';'); | 211 | string::size_type sc = str.find(';'); |
208 | string s; | 212 | string s; |
209 | if(sc==string::npos) { | 213 | if(sc==string::npos) { |
210 | s = str; | 214 | s = str; |
211 | str.erase(); | 215 | str.erase(); |
212 | }else{ | 216 | }else{ |
213 | s = str.substr(0,sc); | 217 | s = str.substr(0,sc); |
214 | str.erase(0,sc+1); | 218 | str.erase(0,sc+1); |
215 | } | 219 | } |
216 | string::size_type nsp=s.find_first_not_of(" \t"); | 220 | string::size_type nsp=s.find_first_not_of(" \t"); |
217 | if((nsp!=string::npos) && nsp) | 221 | if((nsp!=string::npos) && nsp) |
218 | s.erase(0,nsp); | 222 | s.erase(0,nsp); |
219 | string::size_type eq=s.find('='); | 223 | string::size_type eq=s.find('='); |
220 | if(eq==string::npos) | 224 | if(eq==string::npos) |
221 | continue; | 225 | continue; |
222 | string n = s.substr(0,eq); | 226 | string n = s.substr(0,eq); |
223 | s.erase(0,eq+1); | 227 | s.erase(0,eq+1); |
224 | nsp = n.find_last_not_of(" \t"); | 228 | nsp = n.find_last_not_of(" \t"); |
225 | n.erase(nsp+1); | 229 | n.erase(nsp+1); |
226 | nsp = s.find_first_not_of(" \t"); | 230 | nsp = s.find_first_not_of(" \t"); |
227 | string v; | 231 | string v; |
228 | if(nsp!=string::npos) | 232 | if(nsp!=string::npos) |
229 | v = s.substr(nsp); | 233 | v = s.substr(nsp); |
230 | else | 234 | else |
231 | v = s; | 235 | v = s; |
232 | nsp = v.find_last_not_of(" \t"); | 236 | nsp = v.find_last_not_of(" \t"); |
233 | if(nsp==string::npos) | 237 | if(nsp==string::npos) |
234 | v.erase(); | 238 | v.erase(); |
235 | else | 239 | else |
236 | v.erase(nsp+1); | 240 | v.erase(nsp+1); |
237 | cookie& c = (*this)[n]; | 241 | set_cookie(cookie(n,v)); |
238 | c.set_name(n); c.set_value(v); | ||
239 | } | 242 | } |
240 | } | 243 | } |
241 | 244 | ||
242 | } | 245 | } |