Branch data Line data Source code
1 : : /*
2 : : * Copyright 2006-2009 Savarese Software Research Corporation
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * http://www.savarese.com/software/ApacheLicense-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : /**
18 : : * @file
19 : : * This header defines functions for parsing a URL query string.
20 : : */
21 : :
22 : : #ifndef __SSRC_WSPR_FCGI_PARSE_QUERY_H
23 : : #define __SSRC_WSPR_FCGI_PARSE_QUERY_H
24 : :
25 : : #include <ssrc/wispers/fcgi/FCGIRequest.h>
26 : : #include <ssrc/wispers/fcgi/URI.h>
27 : : #include <ssrc/wispers/utility/WebStrings.h>
28 : :
29 : : #include <boost/algorithm/string/trim.hpp>
30 : :
31 : : __BEGIN_NS_SSRC_WSPR_FCGI
32 : :
33 : : template<typename container_type>
34 : 5 : void parse_query_string(const string & query_str, container_type & parameters) {
35 : : using NS_SSRC_WSPR_UTILITY::unescape_url;
36 : :
37 [ - + ]: 5 : if(query_str.empty())
38 : 0 : return;
39 : :
40 : 5 : string::size_type and_pos = query_str.find('&');
41 : 5 : string::size_type eq_pos = query_str.find('=');
42 : 5 : string::size_type pos = 0;
43 [ + - + - ]: 10 : string name, value;
44 : :
45 [ + + ]: 18 : while(eq_pos != string::npos) {
46 [ + + + + + : 28 : while(and_pos < eq_pos || and_pos == string::npos) {
+ ]
47 [ + + ]: 12 : if(and_pos == string::npos) {
48 [ + - ]: 5 : and_pos = query_str.size();
49 : : } else {
50 : 7 : pos = and_pos + 1;
51 [ + - ]: 7 : and_pos = query_str.find('&', pos);
52 : : }
53 : : }
54 : :
55 : 8 : const string::size_type key_size = eq_pos - pos;
56 : 8 : const string::size_type value_size = and_pos - eq_pos - 1;
57 : :
58 [ + + ]: 8 : if(key_size > 0) {
59 [ + - ]: 7 : name.assign(query_str, pos, key_size);
60 [ + - ]: 7 : value.assign(query_str, eq_pos + 1, value_size);
61 [ + - ]: 7 : unescape_url(name);
62 [ + - ]: 7 : unescape_url(value);
63 : :
64 : : // We do not allow leading or trailing whitespace in input values.
65 [ + - ]: 7 : boost::algorithm::trim(value);
66 : :
67 [ + - + - + : 7 : parameters.insert(typename container_type::value_type(name, value));
- ]
68 : : }
69 : :
70 [ + - ]: 8 : eq_pos = query_str.find('=', and_pos);
71 : : }
72 : : }
73 : :
74 : : template<typename container_type>
75 : : void parse_get_parameters(const FCGIRequest & request,
76 : : container_type & parameters)
77 : : {
78 : : const char *query_str = request.fcgx_get_param("QUERY_STRING");
79 : :
80 : : if(!query_str || *query_str == 0) {
81 : : const char *request_uri = request.fcgx_get_param("REQUEST_URI");
82 : : if(request_uri) {
83 : : URI uri(request_uri);
84 : : parse_query_string(uri.query(), parameters);
85 : : }
86 : : } else
87 : : parse_query_string(query_str, parameters);
88 : : }
89 : :
90 : : template<typename container_type>
91 : : container_type parse_get_parameters(const FCGIRequest & request) {
92 : : container_type parameters;
93 : : parse_get_parameters(request, parameters);
94 : : return parameters;
95 : : }
96 : :
97 : : template<typename container_type>
98 : : void parse_post_parameters(const FCGIRequest & request,
99 : : container_type & parameters)
100 : : {
101 : : // TODO: Check that content length is less than some maximum value first.
102 : : if(request.content_type().find("application/x-www-form-urlencoded") == 0) {
103 : : long length = request.content_length();
104 : :
105 : : if(length > 0) {
106 : : string data(length, ' ');
107 : : int bytes_read = 0, total = 0;
108 : :
109 : : // Using &data[i] as a contiguous buffer may not work with some
110 : : // STL implementations, but C++ 0x requires the behavior.
111 : : while(length > 0) {
112 : : bytes_read = request.fcgx_get_str(&data[total], length);
113 : : if(bytes_read <= 0)
114 : : break;
115 : : total+=bytes_read;
116 : : length-=bytes_read;
117 : : }
118 : :
119 : : // Ignore short reads. The error will be handled elsewhere.
120 : : if(length != 0)
121 : : data.resize(total);
122 : :
123 : : parse_query_string(data, parameters);
124 : : }
125 : : }// else if(type == "multipart/form-data") {
126 : : // TODO: Open issue and implement rfc2388 handling. Since
127 : : // this could involve the uploading of a big file, we want to
128 : : // set some kind of a flag that is used by FCGIProcessor to
129 : : // schedule the file transfer via its event loop. The same
130 : : // could be done for application/x-www-form-urlencoded. We
131 : : // should make the decision based on the ContentLength.
132 : : //}
133 : : }
134 : :
135 : : template<typename container_type>
136 : : container_type parse_post_parameters(const FCGIRequest & request) {
137 : : container_type parameters;
138 : : parse_post_parameters(request, parameters);
139 : : return parameters;
140 : : }
141 : :
142 : : __END_NS_SSRC_WSPR_FCGI
143 : :
144 : : #endif
|