Skip to content

Commit 1c3aed3

Browse files
committed
Copy old HttpUtils.parseQueryString from Servlet API
For now, let's propagate this here, to allow moving forward. Need to step back and decide if this is still needed.
1 parent 9c03176 commit 1c3aed3

File tree

2 files changed

+128
-1
lines changed

2 files changed

+128
-1
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 1997-2018 Oracle and/or its affiliates and others.
3+
* All rights reserved.
4+
* Copyright 2004 The Apache Software Foundation
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.jruby.rack.servlet;
20+
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
import java.util.StringTokenizer;
24+
25+
/**
26+
* @deprecated As of Java(tm) Servlet API 2.3. These methods were only useful with the default encoding and have been
27+
* moved to the request interfaces. Propagated to jruby-racl from old Javax Servlet API <= 4.0.
28+
*
29+
*/
30+
@Deprecated()
31+
public class HttpUtils {
32+
33+
private HttpUtils() {}
34+
35+
/**
36+
* Parses a query string passed from the client to the server and builds a <code>HashMap</code> object with
37+
* key-value pairs. The query string should be in the form of a string packaged by the GET or POST method, that is,
38+
* it should have key-value pairs in the form <i>key=value</i>, with each pair separated from the next by a &amp;
39+
* character.
40+
*
41+
* <p>
42+
* A key can appear more than once in the query string with different values. However, the key appears only once in
43+
* the HashMap, with its value being an array of strings containing the multiple values sent by the query string.
44+
*
45+
* <p>
46+
* The keys and values in the HashMap are stored in their decoded form, so any + characters are converted to
47+
* spaces, and characters sent in hexadecimal notation (like <i>%xx</i>) are converted to ASCII characters.
48+
*
49+
* @param s a string containing the query to be parsed
50+
*
51+
* @return a <code>Map</code> object built from the parsed key-value pairs
52+
*
53+
* @exception IllegalArgumentException if the query string is invalid
54+
*/
55+
public static Map<String, String[]> parseQueryString(String s) {
56+
57+
String valArray[];
58+
59+
if (s == null) {
60+
throw new IllegalArgumentException();
61+
}
62+
63+
Map<String, String[]> ht = new HashMap<>();
64+
StringBuilder sb = new StringBuilder();
65+
StringTokenizer st = new StringTokenizer(s, "&");
66+
while (st.hasMoreTokens()) {
67+
String pair = st.nextToken();
68+
int pos = pair.indexOf('=');
69+
if (pos == -1) {
70+
// XXX
71+
// should give more detail about the illegal argument
72+
throw new IllegalArgumentException();
73+
}
74+
String key = parseName(pair.substring(0, pos), sb);
75+
String val = parseName(pair.substring(pos + 1), sb);
76+
if (ht.containsKey(key)) {
77+
String oldVals[] = ht.get(key);
78+
valArray = new String[oldVals.length + 1];
79+
System.arraycopy(oldVals, 0, valArray, 0, oldVals.length);
80+
valArray[oldVals.length] = val;
81+
} else {
82+
valArray = new String[1];
83+
valArray[0] = val;
84+
}
85+
ht.put(key, valArray);
86+
}
87+
88+
return ht;
89+
}
90+
91+
/*
92+
* Parse a name in the query string.
93+
*/
94+
private static String parseName(String s, StringBuilder sb) {
95+
sb.setLength(0);
96+
for (int i = 0; i < s.length(); i++) {
97+
char c = s.charAt(i);
98+
switch (c) {
99+
case '+':
100+
sb.append(' ');
101+
break;
102+
case '%':
103+
try {
104+
sb.append((char) Integer.parseInt(s.substring(i + 1, i + 3), 16));
105+
i += 2;
106+
} catch (NumberFormatException e) {
107+
// XXX
108+
// need to be more specific about illegal arg
109+
throw new IllegalArgumentException();
110+
} catch (StringIndexOutOfBoundsException e) {
111+
String rest = s.substring(i);
112+
sb.append(rest);
113+
if (rest.length() == 2)
114+
i++;
115+
}
116+
117+
break;
118+
default:
119+
sb.append(c);
120+
break;
121+
}
122+
}
123+
124+
return sb.toString();
125+
}
126+
127+
}

src/main/ruby/rack/handler/servlet/servlet_env.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ def query_values(key)
184184
end
185185

186186
def parse_query_string
187-
Java::JakartaServletHttp::HttpUtils.parseQueryString(query_string)
187+
Java::OrgJrubyRackServlet::HttpUtils.parseQueryString(query_string)
188188
end
189189

190190
def mark_parameter_error(msg)

0 commit comments

Comments
 (0)