JSONString interface allows a toJSONString()
4 | * method so that a class can change the behavior of
5 | * JSONObject.toString(), JSONArray.toString(),
6 | * and JSONWriter.value(Object). The
7 | * toJSONString method will be used instead of the default behavior
8 | * of using the Object's toString() method and quoting the result.
9 | */
10 | public interface JSONString {
11 | /**
12 | * The toJSONString method allows a class to produce its own JSON
13 | * serialization.
14 | *
15 | * @return A strictly syntactically correct JSON text.
16 | */
17 | public String toJSONString();
18 | }
19 |
--------------------------------------------------------------------------------
/src/connect2/GameInfo.java:
--------------------------------------------------------------------------------
1 | package connect2;
2 |
3 | import java.net.InetAddress;
4 | import java.net.UnknownHostException;
5 |
6 | public class GameInfo {
7 | int uid;
8 | InetAddress remoteAddress;
9 | int remotePort;
10 | int hostCounter;
11 | String gamename;
12 | String map;
13 | String extra;
14 | long millis;
15 |
16 | public GameInfo(int uid, byte[] addr, int port, int hostCounter, String gamename, String map, String extra) {
17 | this.uid = uid;
18 | this.remotePort = port;
19 | this.hostCounter = hostCounter;
20 | this.gamename = gamename;
21 | this.map = map;
22 | this.extra = extra;
23 | this.millis = System.currentTimeMillis();
24 |
25 | try {
26 | remoteAddress = InetAddress.getByAddress(addr);
27 | } catch(UnknownHostException uhe) {
28 | System.out.println("[GameInfo] Error: unknown host on addr bytes: " + uhe.getLocalizedMessage());
29 | remoteAddress = null;
30 | }
31 | }
32 |
33 | public boolean expired() {
34 | return (System.currentTimeMillis() - this.millis) > 30000;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/org/json/JSONException.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /**
4 | * The JSONException is thrown by the JSON.org classes when things are amiss.
5 | *
6 | * @author JSON.org
7 | * @version 2015-12-09
8 | */
9 | public class JSONException extends RuntimeException {
10 | /** Serialization ID */
11 | private static final long serialVersionUID = 0;
12 |
13 | /**
14 | * Constructs a JSONException with an explanatory message.
15 | *
16 | * @param message
17 | * Detail about the reason for the exception.
18 | */
19 | public JSONException(final String message) {
20 | super(message);
21 | }
22 |
23 | /**
24 | * Constructs a JSONException with an explanatory message and cause.
25 | *
26 | * @param message
27 | * Detail about the reason for the exception.
28 | * @param cause
29 | * The cause.
30 | */
31 | public JSONException(final String message, final Throwable cause) {
32 | super(message, cause);
33 | }
34 |
35 | /**
36 | * Constructs a new JSONException with the specified cause.
37 | *
38 | * @param cause
39 | * The cause.
40 | */
41 | public JSONException(final Throwable cause) {
42 | super(cause.getMessage(), cause);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/connect2/Main.java:
--------------------------------------------------------------------------------
1 | package connect2;
2 |
3 | import java.awt.*;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 |
7 | public class Main {
8 | public static Map""
40 | * will have the Bean parser fall back to the default field name processing.
41 | */
42 | public @interface JSONPropertyName {
43 | /**
44 | * @return The name of the property as to be used in the JSON Object.
45 | */
46 | String value();
47 | }
48 |
--------------------------------------------------------------------------------
/src/connect2/ECList.java:
--------------------------------------------------------------------------------
1 | package connect2;
2 |
3 | import org.json.JSONArray;
4 |
5 | import javax.net.ssl.HttpsURLConnection;
6 | import java.nio.ByteBuffer;
7 | import java.util.List;
8 |
9 | public class ECList implements Runnable {
10 | ECHost host;
11 | ByteBuffer buf;
12 | String filter;
13 | List
35 | * A JSONStringer instance provides a value method for appending
36 | * values to the
37 | * text, and a key
38 | * method for adding keys before values in objects. There are array
39 | * and endArray methods that make and bound array values, and
40 | * object and endObject methods which make and bound
41 | * object values. All of these methods return the JSONWriter instance,
42 | * permitting cascade style. For example,
43 | * myString = new JSONStringer()
44 | * .object()
45 | * .key("JSON")
46 | * .value("Hello, World!")
47 | * .endObject()
48 | * .toString(); which produces the string
49 | * {"JSON":"Hello, World!"}
50 | *
51 | * The first method called must be array or object.
52 | * There are no methods for adding commas or colons. JSONStringer adds them for
53 | * you. Objects and arrays can be nested up to 20 levels deep.
54 | *
55 | * This can sometimes be easier than using a JSONObject to build a string.
56 | * @author JSON.org
57 | * @version 2015-12-09
58 | */
59 | public class JSONStringer extends JSONWriter {
60 | /**
61 | * Make a fresh JSONStringer. It can be used to build one JSON text.
62 | */
63 | public JSONStringer() {
64 | super(new StringWriter());
65 | }
66 |
67 | /**
68 | * Return the JSON text. This method is used to obtain the product of the
69 | * JSONStringer instance. It will return Login with your WC3Connect account, or create a new one. If you previously logged in with your entgaming.net forum account, you can login with the same username and password.
33 | * Each row of text represents a row in a table or a data record. Each row
34 | * ends with a NEWLINE character. Each row contains one or more values.
35 | * Values are separated by commas. A value can contain any character except
36 | * for comma, unless is is wrapped in single quotes or double quotes.
37 | *
38 | * The first row usually contains the names of the columns.
39 | *
40 | * A comma delimited list can be converted into a JSONArray of JSONObjects.
41 | * The names for the elements in the JSONObjects can be taken from the names
42 | * in the first row.
43 | * @author JSON.org
44 | * @version 2016-05-01
45 | */
46 | public class CDL {
47 |
48 | /**
49 | * Get the next value. The value can be wrapped in quotes. The value can
50 | * be empty.
51 | * @param x A JSONTokener of the source text.
52 | * @return The value string, or null if empty.
53 | * @throws JSONException if the quoted string is badly formed.
54 | */
55 | private static String getValue(JSONTokener x) throws JSONException {
56 | char c;
57 | char q;
58 | StringBuffer sb;
59 | do {
60 | c = x.next();
61 | } while (c == ' ' || c == '\t');
62 | switch (c) {
63 | case 0:
64 | return null;
65 | case '"':
66 | case '\'':
67 | q = c;
68 | sb = new StringBuffer();
69 | for (;;) {
70 | c = x.next();
71 | if (c == q) {
72 | //Handle escaped double-quote
73 | char nextC = x.next();
74 | if(nextC != '\"') {
75 | // if our quote was the end of the file, don't step
76 | if(nextC > 0) {
77 | x.back();
78 | }
79 | break;
80 | }
81 | }
82 | if (c == 0 || c == '\n' || c == '\r') {
83 | throw x.syntaxError("Missing close quote '" + q + "'.");
84 | }
85 | sb.append(c);
86 | }
87 | return sb.toString();
88 | case ',':
89 | x.back();
90 | return "";
91 | default:
92 | x.back();
93 | return x.nextTo(',');
94 | }
95 | }
96 |
97 | /**
98 | * Produce a JSONArray of strings from a row of comma delimited values.
99 | * @param x A JSONTokener of the source text.
100 | * @return A JSONArray of strings.
101 | * @throws JSONException
102 | */
103 | public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
104 | JSONArray ja = new JSONArray();
105 | for (;;) {
106 | String value = getValue(x);
107 | char c = x.next();
108 | if (value == null ||
109 | (ja.length() == 0 && value.length() == 0 && c != ',')) {
110 | return null;
111 | }
112 | ja.put(value);
113 | for (;;) {
114 | if (c == ',') {
115 | break;
116 | }
117 | if (c != ' ') {
118 | if (c == '\n' || c == '\r' || c == 0) {
119 | return ja;
120 | }
121 | throw x.syntaxError("Bad character '" + c + "' (" +
122 | (int)c + ").");
123 | }
124 | c = x.next();
125 | }
126 | }
127 | }
128 |
129 | /**
130 | * Produce a JSONObject from a row of comma delimited text, using a
131 | * parallel JSONArray of strings to provides the names of the elements.
132 | * @param names A JSONArray of names. This is commonly obtained from the
133 | * first row of a comma delimited text file using the rowToJSONArray
134 | * method.
135 | * @param x A JSONTokener of the source text.
136 | * @return A JSONObject combining the names and values.
137 | * @throws JSONException
138 | */
139 | public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
140 | throws JSONException {
141 | JSONArray ja = rowToJSONArray(x);
142 | return ja != null ? ja.toJSONObject(names) : null;
143 | }
144 |
145 | /**
146 | * Produce a comma delimited text row from a JSONArray. Values containing
147 | * the comma character will be quoted. Troublesome characters may be
148 | * removed.
149 | * @param ja A JSONArray of strings.
150 | * @return A string ending in NEWLINE.
151 | */
152 | public static String rowToString(JSONArray ja) {
153 | StringBuilder sb = new StringBuilder();
154 | for (int i = 0; i < ja.length(); i += 1) {
155 | if (i > 0) {
156 | sb.append(',');
157 | }
158 | Object object = ja.opt(i);
159 | if (object != null) {
160 | String string = object.toString();
161 | if (string.length() > 0 && (string.indexOf(',') >= 0 ||
162 | string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 ||
163 | string.indexOf(0) >= 0 || string.charAt(0) == '"')) {
164 | sb.append('"');
165 | int length = string.length();
166 | for (int j = 0; j < length; j += 1) {
167 | char c = string.charAt(j);
168 | if (c >= ' ' && c != '"') {
169 | sb.append(c);
170 | }
171 | }
172 | sb.append('"');
173 | } else {
174 | sb.append(string);
175 | }
176 | }
177 | }
178 | sb.append('\n');
179 | return sb.toString();
180 | }
181 |
182 | /**
183 | * Produce a JSONArray of JSONObjects from a comma delimited text string,
184 | * using the first row as a source of names.
185 | * @param string The comma delimited text.
186 | * @return A JSONArray of JSONObjects.
187 | * @throws JSONException
188 | */
189 | public static JSONArray toJSONArray(String string) throws JSONException {
190 | return toJSONArray(new JSONTokener(string));
191 | }
192 |
193 | /**
194 | * Produce a JSONArray of JSONObjects from a comma delimited text string,
195 | * using the first row as a source of names.
196 | * @param x The JSONTokener containing the comma delimited text.
197 | * @return A JSONArray of JSONObjects.
198 | * @throws JSONException
199 | */
200 | public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
201 | return toJSONArray(rowToJSONArray(x), x);
202 | }
203 |
204 | /**
205 | * Produce a JSONArray of JSONObjects from a comma delimited text string
206 | * using a supplied JSONArray as the source of element names.
207 | * @param names A JSONArray of strings.
208 | * @param string The comma delimited text.
209 | * @return A JSONArray of JSONObjects.
210 | * @throws JSONException
211 | */
212 | public static JSONArray toJSONArray(JSONArray names, String string)
213 | throws JSONException {
214 | return toJSONArray(names, new JSONTokener(string));
215 | }
216 |
217 | /**
218 | * Produce a JSONArray of JSONObjects from a comma delimited text string
219 | * using a supplied JSONArray as the source of element names.
220 | * @param names A JSONArray of strings.
221 | * @param x A JSONTokener of the source text.
222 | * @return A JSONArray of JSONObjects.
223 | * @throws JSONException
224 | */
225 | public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
226 | throws JSONException {
227 | if (names == null || names.length() == 0) {
228 | return null;
229 | }
230 | JSONArray ja = new JSONArray();
231 | for (;;) {
232 | JSONObject jo = rowToJSONObject(names, x);
233 | if (jo == null) {
234 | break;
235 | }
236 | ja.put(jo);
237 | }
238 | if (ja.length() == 0) {
239 | return null;
240 | }
241 | return ja;
242 | }
243 |
244 |
245 | /**
246 | * Produce a comma delimited text from a JSONArray of JSONObjects. The
247 | * first row will be a list of names obtained by inspecting the first
248 | * JSONObject.
249 | * @param ja A JSONArray of JSONObjects.
250 | * @return A comma delimited text.
251 | * @throws JSONException
252 | */
253 | public static String toString(JSONArray ja) throws JSONException {
254 | JSONObject jo = ja.optJSONObject(0);
255 | if (jo != null) {
256 | JSONArray names = jo.names();
257 | if (names != null) {
258 | return rowToString(names) + toString(names, ja);
259 | }
260 | }
261 | return null;
262 | }
263 |
264 | /**
265 | * Produce a comma delimited text from a JSONArray of JSONObjects using
266 | * a provided list of names. The list of names is not included in the
267 | * output.
268 | * @param names A JSONArray of strings.
269 | * @param ja A JSONArray of JSONObjects.
270 | * @return A comma delimited text.
271 | * @throws JSONException
272 | */
273 | public static String toString(JSONArray names, JSONArray ja)
274 | throws JSONException {
275 | if (names == null || names.length() == 0) {
276 | return null;
277 | }
278 | StringBuffer sb = new StringBuffer();
279 | for (int i = 0; i < ja.length(); i += 1) {
280 | JSONObject jo = ja.optJSONObject(i);
281 | if (jo != null) {
282 | sb.append(rowToString(jo.toJSONArray(names)));
283 | }
284 | }
285 | return sb.toString();
286 | }
287 | }
288 |
--------------------------------------------------------------------------------
/src/org/json/JSONPointer.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | import static java.lang.String.format;
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.net.URLDecoder;
7 | import java.net.URLEncoder;
8 | import java.util.ArrayList;
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | /*
13 | Copyright (c) 2002 JSON.org
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy
16 | of this software and associated documentation files (the "Software"), to deal
17 | in the Software without restriction, including without limitation the rights
18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | copies of the Software, and to permit persons to whom the Software is
20 | furnished to do so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in all
23 | copies or substantial portions of the Software.
24 |
25 | The Software shall be used for Good, not Evil.
26 |
27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 | SOFTWARE.
34 | */
35 |
36 | /**
37 | * A JSON Pointer is a simple query language defined for JSON documents by
38 | * RFC 6901.
39 | *
40 | * In a nutshell, JSONPointer allows the user to navigate into a JSON document
41 | * using strings, and retrieve targeted objects, like a simple form of XPATH.
42 | * Path segments are separated by the '/' char, which signifies the root of
43 | * the document when it appears as the first char of the string. Array
44 | * elements are navigated using ordinals, counting from 0. JSONPointer strings
45 | * may be extended to any arbitrary number of segments. If the navigation
46 | * is successful, the matched item is returned. A matched item may be a
47 | * JSONObject, a JSONArray, or a JSON value. If the JSONPointer string building
48 | * fails, an appropriate exception is thrown. If the navigation fails to find
49 | * a match, a JSONPointerException is thrown.
50 | *
51 | * @author JSON.org
52 | * @version 2016-05-14
53 | */
54 | public class JSONPointer {
55 |
56 | // used for URL encoding and decoding
57 | private static final String ENCODING = "utf-8";
58 |
59 | /**
60 | * This class allows the user to build a JSONPointer in steps, using
61 | * exactly one segment in each step.
62 | */
63 | public static class Builder {
64 |
65 | // Segments for the eventual JSONPointer string
66 | private final List
37 | * A JSONWriter instance provides a
52 | * The first method called must be
56 | * This can sometimes be easier than using a JSONObject to build a string.
57 | * @author JSON.org
58 | * @version 2016-08-08
59 | */
60 | public class JSONWriter {
61 | private static final int maxdepth = 200;
62 |
63 | /**
64 | * The comma flag determines if a comma should be output before the next
65 | * value.
66 | */
67 | private boolean comma;
68 |
69 | /**
70 | * The current mode. Values:
71 | * 'a' (array),
72 | * 'd' (done),
73 | * 'i' (initial),
74 | * 'k' (key),
75 | * 'o' (object).
76 | */
77 | protected char mode;
78 |
79 | /**
80 | * The object/array stack.
81 | */
82 | private final JSONObject stack[];
83 |
84 | /**
85 | * The stack top index. A value of 0 indicates that the stack is empty.
86 | */
87 | private int top;
88 |
89 | /**
90 | * The writer that will receive the output.
91 | */
92 | protected Appendable writer;
93 |
94 | /**
95 | * Make a fresh JSONWriter. It can be used to build one JSON text.
96 | */
97 | public JSONWriter(Appendable w) {
98 | this.comma = false;
99 | this.mode = 'i';
100 | this.stack = new JSONObject[maxdepth];
101 | this.top = 0;
102 | this.writer = w;
103 | }
104 |
105 | /**
106 | * Append a value.
107 | * @param string A string value.
108 | * @return this
109 | * @throws JSONException If the value is out of sequence.
110 | */
111 | private JSONWriter append(String string) throws JSONException {
112 | if (string == null) {
113 | throw new JSONException("Null pointer");
114 | }
115 | if (this.mode == 'o' || this.mode == 'a') {
116 | try {
117 | if (this.comma && this.mode == 'a') {
118 | this.writer.append(',');
119 | }
120 | this.writer.append(string);
121 | } catch (IOException e) {
122 | // Android as of API 25 does not support this exception constructor
123 | // however we won't worry about it. If an exception is happening here
124 | // it will just throw a "Method not found" exception instead.
125 | throw new JSONException(e);
126 | }
127 | if (this.mode == 'o') {
128 | this.mode = 'k';
129 | }
130 | this.comma = true;
131 | return this;
132 | }
133 | throw new JSONException("Value out of sequence.");
134 | }
135 |
136 | /**
137 | * Begin appending a new array. All values until the balancing
138 | *
312 | * Warning: This method assumes that the data structure is acyclical.
313 | *
314 | * @param value
315 | * The value to be serialized.
316 | * @return a printable, displayable, transmittable representation of the
317 | * object, beginning with null if there was a
70 | * problem in the construction of the JSON text (such as the calls to
71 | * array were not properly balanced with calls to
72 | * endArray).
73 | * @return The JSON text.
74 | */
75 | @Override
76 | public String toString() {
77 | return this.mode == 'd' ? this.writer.toString() : null;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/org/json/CookieList.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | /**
28 | * Convert a web browser cookie list string to a JSONObject and back.
29 | * @author JSON.org
30 | * @version 2015-12-09
31 | */
32 | public class CookieList {
33 |
34 | /**
35 | * Convert a cookie list into a JSONObject. A cookie list is a sequence
36 | * of name/value pairs. The names are separated from the values by '='.
37 | * The pairs are separated by ';'. The names and the values
38 | * will be unescaped, possibly converting '+' and '%' sequences.
39 | *
40 | * To add a cookie to a cookie list,
41 | * cookielistJSONObject.put(cookieJSONObject.getString("name"),
42 | * cookieJSONObject.getString("value"));
43 | * @param string A cookie list string
44 | * @return A JSONObject
45 | * @throws JSONException
46 | */
47 | public static JSONObject toJSONObject(String string) throws JSONException {
48 | JSONObject jo = new JSONObject();
49 | JSONTokener x = new JSONTokener(string);
50 | while (x.more()) {
51 | String name = Cookie.unescape(x.nextTo('='));
52 | x.next('=');
53 | jo.put(name, Cookie.unescape(x.nextTo(';')));
54 | x.next();
55 | }
56 | return jo;
57 | }
58 |
59 | /**
60 | * Convert a JSONObject into a cookie list. A cookie list is a sequence
61 | * of name/value pairs. The names are separated from the values by '='.
62 | * The pairs are separated by ';'. The characters '%', '+', '=', and ';'
63 | * in the names and values are replaced by "%hh".
64 | * @param jo A JSONObject
65 | * @return A cookie list string
66 | * @throws JSONException
67 | */
68 | public static String toString(JSONObject jo) throws JSONException {
69 | boolean b = false;
70 | final StringBuilder sb = new StringBuilder();
71 | // Don't use the new entrySet API to maintain Android support
72 | for (final String key : jo.keySet()) {
73 | final Object value = jo.opt(key);
74 | if (!JSONObject.NULL.equals(value)) {
75 | if (b) {
76 | sb.append(';');
77 | }
78 | sb.append(Cookie.escape(key));
79 | sb.append("=");
80 | sb.append(Cookie.escape(value.toString()));
81 | b = true;
82 | }
83 | }
84 | return sb.toString();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/connect2/Utils.java:
--------------------------------------------------------------------------------
1 | package connect2;
2 |
3 | import java.util.Map;
4 | import java.io.InputStream;
5 | import java.io.IOException;
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.DataOutputStream;
8 | import java.io.OutputStream;
9 | import java.net.URL;
10 | import java.net.URLEncoder;
11 | import java.net.HttpURLConnection;
12 | import com.sun.net.httpserver.HttpExchange;
13 | import org.json.JSONObject;
14 |
15 | public class Utils {
16 | public static ByteArrayOutputStream streamToByteArrayOutputStream(InputStream in) throws IOException {
17 | byte[] buf = new byte[4096];
18 | ByteArrayOutputStream out = new ByteArrayOutputStream();
19 | while(true) {
20 | int n = in.read(buf);
21 | if(n == -1) {
22 | break;
23 | }
24 | out.write(buf, 0, n);
25 | }
26 | return out;
27 | }
28 |
29 | public static byte[] streamToByteArray(InputStream in) throws IOException {
30 | return streamToByteArrayOutputStream(in).toByteArray();
31 | }
32 |
33 | public static String streamToString(InputStream in) throws IOException {
34 | return streamToByteArrayOutputStream(in).toString("UTF-8");
35 | }
36 |
37 | public static String post(String url, byte[] request) throws IOException {
38 | URL u = new URL(url);
39 | HttpURLConnection con = (HttpURLConnection) u.openConnection();
40 | con.setRequestMethod("POST");
41 | con.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
42 | con.setConnectTimeout(5000);
43 | con.setDoOutput(true);
44 | DataOutputStream out = new DataOutputStream(con.getOutputStream());
45 | out.write(request);
46 | out.flush();
47 | out.close();
48 | String response = Utils.streamToString(con.getInputStream());
49 | return response;
50 | }
51 |
52 | public static String postForm(String url, Map{
43 | * Method: "POST" (for example),
44 | * "Request-URI": "/" (for example),
45 | * "HTTP-Version": "HTTP/1.1" (for example)
46 | * }
47 | * A response header will contain
48 | * {
49 | * "HTTP-Version": "HTTP/1.1" (for example),
50 | * "Status-Code": "200" (for example),
51 | * "Reason-Phrase": "OK" (for example)
52 | * }
53 | * In addition, the other parameters in the header will be captured, using
54 | * the HTTP field names as JSON names, so that
55 | * Date: Sun, 26 May 2002 18:06:04 GMT
56 | * Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
57 | * Cache-Control: no-cache
58 | * become
59 | * {...
60 | * Date: "Sun, 26 May 2002 18:06:04 GMT",
61 | * Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
62 | * "Cache-Control": "no-cache",
63 | * ...}
64 | * It does no further checking or conversion. It does not parse dates.
65 | * It does not do '%' transforms on URLs.
66 | * @param string An HTTP header string.
67 | * @return A JSONObject containing the elements and attributes
68 | * of the XML string.
69 | * @throws JSONException
70 | */
71 | public static JSONObject toJSONObject(String string) throws JSONException {
72 | JSONObject jo = new JSONObject();
73 | HTTPTokener x = new HTTPTokener(string);
74 | String token;
75 |
76 | token = x.nextToken();
77 | if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
78 |
79 | // Response
80 |
81 | jo.put("HTTP-Version", token);
82 | jo.put("Status-Code", x.nextToken());
83 | jo.put("Reason-Phrase", x.nextTo('\0'));
84 | x.next();
85 |
86 | } else {
87 |
88 | // Request
89 |
90 | jo.put("Method", token);
91 | jo.put("Request-URI", x.nextToken());
92 | jo.put("HTTP-Version", x.nextToken());
93 | }
94 |
95 | // Fields
96 |
97 | while (x.more()) {
98 | String name = x.nextTo(':');
99 | x.next(':');
100 | jo.put(name, x.nextTo('\0'));
101 | x.next();
102 | }
103 | return jo;
104 | }
105 |
106 |
107 | /**
108 | * Convert a JSONObject into an HTTP header. A request header must contain
109 | * {
110 | * Method: "POST" (for example),
111 | * "Request-URI": "/" (for example),
112 | * "HTTP-Version": "HTTP/1.1" (for example)
113 | * }
114 | * A response header must contain
115 | * {
116 | * "HTTP-Version": "HTTP/1.1" (for example),
117 | * "Status-Code": "200" (for example),
118 | * "Reason-Phrase": "OK" (for example)
119 | * }
120 | * Any other members of the JSONObject will be output as HTTP fields.
121 | * The result will end with two CRLF pairs.
122 | * @param jo A JSONObject
123 | * @return An HTTP header string.
124 | * @throws JSONException if the object does not contain enough
125 | * information.
126 | */
127 | public static String toString(JSONObject jo) throws JSONException {
128 | StringBuilder sb = new StringBuilder();
129 | if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
130 | sb.append(jo.getString("HTTP-Version"));
131 | sb.append(' ');
132 | sb.append(jo.getString("Status-Code"));
133 | sb.append(' ');
134 | sb.append(jo.getString("Reason-Phrase"));
135 | } else if (jo.has("Method") && jo.has("Request-URI")) {
136 | sb.append(jo.getString("Method"));
137 | sb.append(' ');
138 | sb.append('"');
139 | sb.append(jo.getString("Request-URI"));
140 | sb.append('"');
141 | sb.append(' ');
142 | sb.append(jo.getString("HTTP-Version"));
143 | } else {
144 | throw new JSONException("Not enough material for an HTTP header.");
145 | }
146 | sb.append(CRLF);
147 | // Don't use the new entrySet API to maintain Android support
148 | for (final String key : jo.keySet()) {
149 | String value = jo.optString(key);
150 | if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
151 | !"Reason-Phrase".equals(key) && !"Method".equals(key) &&
152 | !"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
153 | sb.append(key);
154 | sb.append(": ");
155 | sb.append(jo.optString(key));
156 | sb.append(CRLF);
157 | }
158 | }
159 | sb.append(CRLF);
160 | return sb.toString();
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/org/json/Cookie.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | /**
28 | * Convert a web browser cookie specification to a JSONObject and back.
29 | * JSON and Cookies are both notations for name/value pairs.
30 | * @author JSON.org
31 | * @version 2015-12-09
32 | */
33 | public class Cookie {
34 |
35 | /**
36 | * Produce a copy of a string in which the characters '+', '%', '=', ';'
37 | * and control characters are replaced with "%hh". This is a gentle form
38 | * of URL encoding, attempting to cause as little distortion to the
39 | * string as possible. The characters '=' and ';' are meta characters in
40 | * cookies. By convention, they are escaped using the URL-encoding. This is
41 | * only a convention, not a standard. Often, cookies are expected to have
42 | * encoded values. We encode '=' and ';' because we must. We encode '%' and
43 | * '+' because they are meta characters in URL encoding.
44 | * @param string The source string.
45 | * @return The escaped result.
46 | */
47 | public static String escape(String string) {
48 | char c;
49 | String s = string.trim();
50 | int length = s.length();
51 | StringBuilder sb = new StringBuilder(length);
52 | for (int i = 0; i < length; i += 1) {
53 | c = s.charAt(i);
54 | if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
55 | sb.append('%');
56 | sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
57 | sb.append(Character.forDigit((char)(c & 0x0f), 16));
58 | } else {
59 | sb.append(c);
60 | }
61 | }
62 | return sb.toString();
63 | }
64 |
65 |
66 | /**
67 | * Convert a cookie specification string into a JSONObject. The string
68 | * will contain a name value pair separated by '='. The name and the value
69 | * will be unescaped, possibly converting '+' and '%' sequences. The
70 | * cookie properties may follow, separated by ';', also represented as
71 | * name=value (except the secure property, which does not have a value).
72 | * The name will be stored under the key "name", and the value will be
73 | * stored under the key "value". This method does not do checking or
74 | * validation of the parameters. It only converts the cookie string into
75 | * a JSONObject.
76 | * @param string The cookie specification string.
77 | * @return A JSONObject containing "name", "value", and possibly other
78 | * members.
79 | * @throws JSONException
80 | */
81 | public static JSONObject toJSONObject(String string) throws JSONException {
82 | String name;
83 | JSONObject jo = new JSONObject();
84 | Object value;
85 | JSONTokener x = new JSONTokener(string);
86 | jo.put("name", x.nextTo('='));
87 | x.next('=');
88 | jo.put("value", x.nextTo(';'));
89 | x.next();
90 | while (x.more()) {
91 | name = unescape(x.nextTo("=;"));
92 | if (x.next() != '=') {
93 | if (name.equals("secure")) {
94 | value = Boolean.TRUE;
95 | } else {
96 | throw x.syntaxError("Missing '=' in cookie parameter.");
97 | }
98 | } else {
99 | value = unescape(x.nextTo(';'));
100 | x.next();
101 | }
102 | jo.put(name, value);
103 | }
104 | return jo;
105 | }
106 |
107 |
108 | /**
109 | * Convert a JSONObject into a cookie specification string. The JSONObject
110 | * must contain "name" and "value" members.
111 | * If the JSONObject contains "expires", "domain", "path", or "secure"
112 | * members, they will be appended to the cookie specification string.
113 | * All other members are ignored.
114 | * @param jo A JSONObject
115 | * @return A cookie specification string
116 | * @throws JSONException
117 | */
118 | public static String toString(JSONObject jo) throws JSONException {
119 | StringBuilder sb = new StringBuilder();
120 |
121 | sb.append(escape(jo.getString("name")));
122 | sb.append("=");
123 | sb.append(escape(jo.getString("value")));
124 | if (jo.has("expires")) {
125 | sb.append(";expires=");
126 | sb.append(jo.getString("expires"));
127 | }
128 | if (jo.has("domain")) {
129 | sb.append(";domain=");
130 | sb.append(escape(jo.getString("domain")));
131 | }
132 | if (jo.has("path")) {
133 | sb.append(";path=");
134 | sb.append(escape(jo.getString("path")));
135 | }
136 | if (jo.optBoolean("secure")) {
137 | sb.append(";secure");
138 | }
139 | return sb.toString();
140 | }
141 |
142 | /**
143 | * Convert %hh sequences to single characters, and
144 | * convert plus to space.
145 | * @param string A string that may contain
146 | * + (plus) and
147 | * %hh sequences.
148 | * @return The unescaped string.
149 | */
150 | public static String unescape(String string) {
151 | int length = string.length();
152 | StringBuilder sb = new StringBuilder(length);
153 | for (int i = 0; i < length; ++i) {
154 | char c = string.charAt(i);
155 | if (c == '+') {
156 | c = ' ';
157 | } else if (c == '%' && i + 2 < length) {
158 | int d = JSONTokener.dehexchar(string.charAt(i + 1));
159 | int e = JSONTokener.dehexchar(string.charAt(i + 2));
160 | if (d >= 0 && e >= 0) {
161 | c = (char)(d * 16 + e);
162 | i += 2;
163 | }
164 | }
165 | sb.append(c);
166 | }
167 | return sb.toString();
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/connect2/ECHost.java:
--------------------------------------------------------------------------------
1 | package connect2;
2 |
3 | import java.awt.Color;
4 | import java.io.IOException;
5 | import java.net.DatagramPacket;
6 | import java.net.DatagramSocket;
7 | import java.net.InetAddress;
8 | import java.net.InetSocketAddress;
9 | import java.net.ServerSocket;
10 | import java.net.Socket;
11 | import java.net.SocketAddress;
12 | import java.net.UnknownHostException;
13 | import java.nio.ByteBuffer;
14 | import java.nio.ByteOrder;
15 | import java.util.ArrayList;
16 | import java.util.Map.Entry;
17 | import java.util.HashMap;
18 | import java.util.Iterator;
19 | import java.util.List;
20 | import java.util.Map;
21 |
22 | public class ECHost implements Runnable {
23 | MapLogin
16 | ')
179 | .addClass('game')
180 | .data('key', key)
181 | .data('uid', game.uid);
182 | for(var i = 0; i < cols.length; i++) {
183 | var uiCol = $(' ').text(cols[i]);
184 | uiRow = uiRow.append(uiCol);
185 | }
186 | if(game.app_game) {
187 | uiRow = uiRow.data('gameid', game.app_game.id);
188 | }
189 | if(lastRow) {
190 | lastRow.after(uiRow);
191 | lastRow = uiRow;
192 | } else {
193 | tbody.prepend(uiRow);
194 | lastRow = uiRow;
195 | }
196 | }
197 | }
198 | for(var key in existingRows) {
199 | existingRows[key].remove();
200 | }
201 | };
202 |
203 | var getRefreshTime = function(counter) {
204 | if(counter && counter < 3) {
205 | return 1000;
206 | } else {
207 | return 3000;
208 | }
209 | };
210 |
211 | var getGames = function(counter) {
212 | $.post('/games', function(data) {
213 | setGames($('#public-tbody'), data.publicGames);
214 | setGames($('#autohost-tbody'), data.autohostGames);
215 | setGames($('#others-tbody'), data.otherGames);
216 | setGames($('#unmoderated-tbody'), data.unmoderatedGames);
217 | }, 'json')
218 | .always(function() {
219 | setTimeout(function() {
220 | getGames(counter + 1);
221 | }, getRefreshTime(counter));
222 | });
223 | };
224 | $('tbody').on('click', 'tr.game', function() {
225 | $('tr.game.selected').removeClass('selected');
226 | $('tr.gameinfo').remove();
227 | $(this).addClass('selected');
228 | var uid = $(this).data('uid');
229 | $.post('/show', {'uid': uid});
230 |
231 | if($(this).data('gameid')) {
232 | var row = $(' ')
233 | .addClass('gameinfo')
234 | .data('gameid', $(this).data('gameid'));
235 | var col = $(' ')
236 | .addClass('gameinfo')
237 | .attr('colspan', 5);
238 | row = row.append(col);
239 | $(this).after(row);
240 | refreshInfo(true);
241 | }
242 | });
243 | $('tbody').on('click', 'tr.gameinfo a', function(e) {
244 | e.preventDefault();
245 | });
246 | var refreshInfo = function(norefresh) {
247 | var row = $('tr.gameinfo');
248 | if(row.length == 0) {
249 | setTimeout(function() {
250 | refreshInfo();
251 | }, getRefreshTime());
252 | return;
253 | }
254 | var gameid = row.data('gameid');
255 | var post = $.post('/gameinfo', {'gameid': gameid}, function(data) {
256 | row.children().html(data);
257 | });
258 | if(!norefresh) {
259 | post.always(function() {
260 | setTimeout(function() {
261 | refreshInfo();
262 | }, getRefreshTime());
263 | });
264 | }
265 | };
266 | getGames(1);
267 | setTimeout(function() {
268 | refreshInfo();
269 | }, 3000);
270 |
271 | var setConfig = function() {
272 | var params = {
273 | 'no_broadcast': $('#cfgNoBroadcast').prop('checked') ? 'yes' : '',
274 | 'enable_lan': $('#cfgEnableLAN').prop('checked') ? 'yes' : '',
275 | 'disable_in_game_refresh': $('#cfgDisableInGameRefresh').prop('checked') ? 'yes' : '',
276 | };
277 | $.post('/set-config', params);
278 | };
279 |
280 | $('#cfgNoBroadcast').change(function() {
281 | setConfig();
282 | });
283 |
284 | $('#cfgEnableLAN').change(function() {
285 | setConfig();
286 | });
287 |
288 | $('#cfgDisableInGameRefresh').change(function() {
289 | setConfig();
290 | });
291 |
292 | var showSettingsInfo = function(msg) {
293 | $('#settingsinfo').text(msg);
294 | $('#settingsinfo').css('display', '');
295 | setTimeout(function() {
296 | $('#settingsinfo').css('display', 'none');
297 | }, 5000);
298 | };
299 |
300 | $('#validate_btn').click(function(e) {
301 | e.preventDefault();
302 | $('#settingsinfo').css('display', 'none');
303 | var params = {
304 | key: $('#validate_key').val(),
305 | };
306 | $('#validate_key').val('');
307 | $.post('/validate', params, function(data) {
308 | if(data.error) {
309 | showSettingsInfo(data.error);
310 | } else {
311 | showSettingsInfo('The validation request was sent successfully! If the key is correct, your WC3Connect account should now be validated in your entgaming.net account.');
312 | }
313 | }, 'json');
314 | $('#validateModal').modal('hide')
315 | });
316 |
317 | $('#wc3backup_btn').click(function(e) {
318 | e.preventDefault();
319 | $('#progresserror').css('display', 'none');
320 | $('#progressprogress').css('display', '');
321 | $('#progressModal').modal('show');
322 | var path = $('#wc3backup_btn').data('path');
323 | $.post('/wc3-backup', {'path': path}, function(data) {
324 | if(data.error) {
325 | $('#progresserror').text(data.error);
326 | $('#progresserror').css('display', '');
327 | $('#progressprogress').css('display', 'none');
328 | return;
329 | }
330 | $('#progressModal').modal('hide');
331 | $('#wc3good_dir').text(data.path);
332 | $('#wc3good_btn').data('path', data.path);
333 | showWC3Alert('wc3gooddiv');
334 | }, 'json');
335 | });
336 |
337 | $('#wc3good_btn').click(function(e) {
338 | e.preventDefault();
339 | var path = $('#wc3good_btn').data('path');
340 | $.post('/wc3-start', {'path': path});
341 | });
342 | };
343 |
--------------------------------------------------------------------------------
/src/org/json/CDL.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2002 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | /**
28 | * This provides static methods to convert comma delimited text into a
29 | * JSONArray, and to convert a JSONArray into comma delimited text. Comma
30 | * delimited text is a very popular format for data interchange. It is
31 | * understood by most database, spreadsheet, and organizer programs.
32 | *
120 | *
121 | * @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
122 | * {@link Builder#append(String)} calls.
123 | */
124 | public static Builder builder() {
125 | return new Builder();
126 | }
127 |
128 | // Segments for the JSONPointer string
129 | private final List
113 | * JSONPointer pointer = JSONPointer.builder()
114 | * .append("obj")
115 | * .append("other~key").append("another/key")
116 | * .append("\"")
117 | * .append(0)
118 | * .build();
119 | * ]]>.
71 | * @throws JSONException If the ]]> is not found.
72 | */
73 | public String nextCDATA() throws JSONException {
74 | char c;
75 | int i;
76 | StringBuilder sb = new StringBuilder();
77 | while (more()) {
78 | c = next();
79 | sb.append(c);
80 | i = sb.length() - 3;
81 | if (i >= 0 && sb.charAt(i) == ']' &&
82 | sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
83 | sb.setLength(i);
84 | return sb.toString();
85 | }
86 | }
87 | throw syntaxError("Unclosed CDATA");
88 | }
89 |
90 |
91 | /**
92 | * Get the next XML outer token, trimming whitespace. There are two kinds
93 | * of tokens: the '<' character which begins a markup tag, and the content
94 | * text between markup tags.
95 | *
96 | * @return A string, or a '<' Character, or null if there is no more
97 | * source text.
98 | * @throws JSONException
99 | */
100 | public Object nextContent() throws JSONException {
101 | char c;
102 | StringBuilder sb;
103 | do {
104 | c = next();
105 | } while (Character.isWhitespace(c));
106 | if (c == 0) {
107 | return null;
108 | }
109 | if (c == '<') {
110 | return XML.LT;
111 | }
112 | sb = new StringBuilder();
113 | for (;;) {
114 | if (c == 0) {
115 | return sb.toString().trim();
116 | }
117 | if (c == '<') {
118 | back();
119 | return sb.toString().trim();
120 | }
121 | if (c == '&') {
122 | sb.append(nextEntity(c));
123 | } else {
124 | sb.append(c);
125 | }
126 | c = next();
127 | }
128 | }
129 |
130 |
131 | /**
132 | * Return the next entity. These entities are translated to Characters:
133 | * & ' > < ".
134 | * @param ampersand An ampersand character.
135 | * @return A Character or an entity String if the entity is not recognized.
136 | * @throws JSONException If missing ';' in XML entity.
137 | */
138 | public Object nextEntity(@SuppressWarnings("unused") char ampersand) throws JSONException {
139 | StringBuilder sb = new StringBuilder();
140 | for (;;) {
141 | char c = next();
142 | if (Character.isLetterOrDigit(c) || c == '#') {
143 | sb.append(Character.toLowerCase(c));
144 | } else if (c == ';') {
145 | break;
146 | } else {
147 | throw syntaxError("Missing ';' in XML entity: &" + sb);
148 | }
149 | }
150 | String string = sb.toString();
151 | return unescapeEntity(string);
152 | }
153 |
154 | /**
155 | * Unescapes an XML entity encoding;
156 | * @param e entity (only the actual entity value, not the preceding & or ending ;
157 | * @return
158 | */
159 | static String unescapeEntity(String e) {
160 | // validate
161 | if (e == null || e.isEmpty()) {
162 | return "";
163 | }
164 | // if our entity is an encoded unicode point, parse it.
165 | if (e.charAt(0) == '#') {
166 | int cp;
167 | if (e.charAt(1) == 'x') {
168 | // hex encoded unicode
169 | cp = Integer.parseInt(e.substring(2), 16);
170 | } else {
171 | // decimal encoded unicode
172 | cp = Integer.parseInt(e.substring(1));
173 | }
174 | return new String(new int[] {cp},0,1);
175 | }
176 | Character knownEntity = entity.get(e);
177 | if(knownEntity==null) {
178 | // we don't know the entity so keep it encoded
179 | return '&' + e + ';';
180 | }
181 | return knownEntity.toString();
182 | }
183 |
184 |
185 | /**
186 | * Returns the next XML meta token. This is used for skipping over
187 | * and ...?> structures.
188 | * @return Syntax characters (< > / = ! ?) are returned as
189 | * Character, and strings and names are returned as Boolean. We don't care
190 | * what the values actually are.
191 | * @throws JSONException If a string is not properly closed or if the XML
192 | * is badly structured.
193 | */
194 | public Object nextMeta() throws JSONException {
195 | char c;
196 | char q;
197 | do {
198 | c = next();
199 | } while (Character.isWhitespace(c));
200 | switch (c) {
201 | case 0:
202 | throw syntaxError("Misshaped meta tag");
203 | case '<':
204 | return XML.LT;
205 | case '>':
206 | return XML.GT;
207 | case '/':
208 | return XML.SLASH;
209 | case '=':
210 | return XML.EQ;
211 | case '!':
212 | return XML.BANG;
213 | case '?':
214 | return XML.QUEST;
215 | case '"':
216 | case '\'':
217 | q = c;
218 | for (;;) {
219 | c = next();
220 | if (c == 0) {
221 | throw syntaxError("Unterminated string");
222 | }
223 | if (c == q) {
224 | return Boolean.TRUE;
225 | }
226 | }
227 | default:
228 | for (;;) {
229 | c = next();
230 | if (Character.isWhitespace(c)) {
231 | return Boolean.TRUE;
232 | }
233 | switch (c) {
234 | case 0:
235 | case '<':
236 | case '>':
237 | case '/':
238 | case '=':
239 | case '!':
240 | case '?':
241 | case '"':
242 | case '\'':
243 | back();
244 | return Boolean.TRUE;
245 | }
246 | }
247 | }
248 | }
249 |
250 |
251 | /**
252 | * Get the next XML Token. These tokens are found inside of angle
253 | * brackets. It may be one of these characters: / > = ! ? or it
254 | * may be a string wrapped in single quotes or double quotes, or it may be a
255 | * name.
256 | * @return a String or a Character.
257 | * @throws JSONException If the XML is not well formed.
258 | */
259 | public Object nextToken() throws JSONException {
260 | char c;
261 | char q;
262 | StringBuilder sb;
263 | do {
264 | c = next();
265 | } while (Character.isWhitespace(c));
266 | switch (c) {
267 | case 0:
268 | throw syntaxError("Misshaped element");
269 | case '<':
270 | throw syntaxError("Misplaced '<'");
271 | case '>':
272 | return XML.GT;
273 | case '/':
274 | return XML.SLASH;
275 | case '=':
276 | return XML.EQ;
277 | case '!':
278 | return XML.BANG;
279 | case '?':
280 | return XML.QUEST;
281 |
282 | // Quoted string
283 |
284 | case '"':
285 | case '\'':
286 | q = c;
287 | sb = new StringBuilder();
288 | for (;;) {
289 | c = next();
290 | if (c == 0) {
291 | throw syntaxError("Unterminated string");
292 | }
293 | if (c == q) {
294 | return sb.toString();
295 | }
296 | if (c == '&') {
297 | sb.append(nextEntity(c));
298 | } else {
299 | sb.append(c);
300 | }
301 | }
302 | default:
303 |
304 | // Name
305 |
306 | sb = new StringBuilder();
307 | for (;;) {
308 | sb.append(c);
309 | c = next();
310 | if (Character.isWhitespace(c)) {
311 | return sb.toString();
312 | }
313 | switch (c) {
314 | case 0:
315 | return sb.toString();
316 | case '>':
317 | case '/':
318 | case '=':
319 | case '!':
320 | case '?':
321 | case '[':
322 | case ']':
323 | back();
324 | return sb.toString();
325 | case '<':
326 | case '"':
327 | case '\'':
328 | throw syntaxError("Bad character in a name");
329 | }
330 | }
331 | }
332 | }
333 |
334 |
335 | /**
336 | * Skip characters until past the requested string.
337 | * If it is not found, we are left at the end of the source with a result of false.
338 | * @param to A string to skip past.
339 | */
340 | // The Android implementation of JSONTokener has a public method of public void skipPast(String to)
341 | // even though ours does not have that method, to have API compatibility, our method in the subclass
342 | // should match.
343 | public void skipPast(String to) {
344 | boolean b;
345 | char c;
346 | int i;
347 | int j;
348 | int offset = 0;
349 | int length = to.length();
350 | char[] circle = new char[length];
351 |
352 | /*
353 | * First fill the circle buffer with as many characters as are in the
354 | * to string. If we reach an early end, bail.
355 | */
356 |
357 | for (i = 0; i < length; i += 1) {
358 | c = next();
359 | if (c == 0) {
360 | return;
361 | }
362 | circle[i] = c;
363 | }
364 |
365 | /* We will loop, possibly for all of the remaining characters. */
366 |
367 | for (;;) {
368 | j = offset;
369 | b = true;
370 |
371 | /* Compare the circle buffer with the to string. */
372 |
373 | for (i = 0; i < length; i += 1) {
374 | if (circle[j] != to.charAt(i)) {
375 | b = false;
376 | break;
377 | }
378 | j += 1;
379 | if (j >= length) {
380 | j -= length;
381 | }
382 | }
383 |
384 | /* If we exit the loop with b intact, then victory is ours. */
385 |
386 | if (b) {
387 | return;
388 | }
389 |
390 | /* Get the next character. If there isn't one, then defeat is ours. */
391 |
392 | c = next();
393 | if (c == 0) {
394 | return;
395 | }
396 | /*
397 | * Shove the character in the circle buffer and advance the
398 | * circle offset. The offset is mod n.
399 | */
400 | circle[offset] = c;
401 | offset += 1;
402 | if (offset >= length) {
403 | offset -= length;
404 | }
405 | }
406 | }
407 | }
408 |
--------------------------------------------------------------------------------
/src/connect2/Web.java:
--------------------------------------------------------------------------------
1 | package connect2;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.HashMap;
6 | import java.util.List;
7 | import java.util.Map;
8 | import java.util.logging.ConsoleHandler;
9 | import java.util.logging.Logger;
10 | import java.util.logging.Level;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.io.OutputStream;
14 | import java.net.InetSocketAddress;
15 | import java.net.URLDecoder;
16 | import com.sun.net.httpserver.HttpServer;
17 | import com.sun.net.httpserver.HttpExchange;
18 | import com.sun.net.httpserver.HttpHandler;
19 | import org.json.JSONObject;
20 | import org.json.JSONArray;
21 |
22 | public class Web {
23 | private LoginResult loginResult = null;
24 | private ECHost host = null;
25 | private ECList list = null;
26 |
27 | public Web() throws IOException {
28 | if(Main.Debug) {
29 | Logger logger = Logger.getLogger("com.sun.net.httpserver");
30 | ConsoleHandler ch = new ConsoleHandler();
31 | logger.setLevel(Level.FINER);
32 | ch.setLevel(Level.FINER);
33 | logger.addHandler(ch);
34 | }
35 | HttpServer server = HttpServer.create(new InetSocketAddress(8333), 0);
36 | server.createContext("/", new FileHandler());
37 | server.createContext("/login", new LoginHandler(this));
38 | server.createContext("/signup", new SignupHandler());
39 | server.createContext("/games", new GamesHandler(this));
40 | server.createContext("/motd", new MotdHandler());
41 | server.createContext("/version", new VersionHandler());
42 | server.createContext("/gameinfo", new GameInfoHandler());
43 | server.createContext("/show", new ShowHandler(this));
44 | server.createContext("/validate", new ValidateHandler(this));
45 | server.setExecutor(null);
46 | server.start();
47 | System.out.println("[web] started on :8333");
48 | }
49 |
50 | static Mapvalue method for appending
38 | * values to the
39 | * text, and a key
40 | * method for adding keys before values in objects. There are array
41 | * and endArray methods that make and bound array values, and
42 | * object and endObject methods which make and bound
43 | * object values. All of these methods return the JSONWriter instance,
44 | * permitting a cascade style. For example,
45 | * new JSONWriter(myWriter)
46 | * .object()
47 | * .key("JSON")
48 | * .value("Hello, World!")
49 | * .endObject(); which writes
50 | * {"JSON":"Hello, World!"}
51 | * array or object.
53 | * There are no methods for adding commas or colons. JSONWriter adds them for
54 | * you. Objects and arrays can be nested up to 200 levels deep.
55 | * endArray will be appended to this array. The
139 | * endArray method must be called to mark the array's end.
140 | * @return this
141 | * @throws JSONException If the nesting is too deep, or if the object is
142 | * started in the wrong place (for example as a key or after the end of the
143 | * outermost array or object).
144 | */
145 | public JSONWriter array() throws JSONException {
146 | if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
147 | this.push(null);
148 | this.append("[");
149 | this.comma = false;
150 | return this;
151 | }
152 | throw new JSONException("Misplaced array.");
153 | }
154 |
155 | /**
156 | * End something.
157 | * @param m Mode
158 | * @param c Closing character
159 | * @return this
160 | * @throws JSONException If unbalanced.
161 | */
162 | private JSONWriter end(char m, char c) throws JSONException {
163 | if (this.mode != m) {
164 | throw new JSONException(m == 'a'
165 | ? "Misplaced endArray."
166 | : "Misplaced endObject.");
167 | }
168 | this.pop(m);
169 | try {
170 | this.writer.append(c);
171 | } catch (IOException e) {
172 | // Android as of API 25 does not support this exception constructor
173 | // however we won't worry about it. If an exception is happening here
174 | // it will just throw a "Method not found" exception instead.
175 | throw new JSONException(e);
176 | }
177 | this.comma = true;
178 | return this;
179 | }
180 |
181 | /**
182 | * End an array. This method most be called to balance calls to
183 | * array.
184 | * @return this
185 | * @throws JSONException If incorrectly nested.
186 | */
187 | public JSONWriter endArray() throws JSONException {
188 | return this.end('a', ']');
189 | }
190 |
191 | /**
192 | * End an object. This method most be called to balance calls to
193 | * object.
194 | * @return this
195 | * @throws JSONException If incorrectly nested.
196 | */
197 | public JSONWriter endObject() throws JSONException {
198 | return this.end('k', '}');
199 | }
200 |
201 | /**
202 | * Append a key. The key will be associated with the next value. In an
203 | * object, every value must be preceded by a key.
204 | * @param string A key string.
205 | * @return this
206 | * @throws JSONException If the key is out of place. For example, keys
207 | * do not belong in arrays or if the key is null.
208 | */
209 | public JSONWriter key(String string) throws JSONException {
210 | if (string == null) {
211 | throw new JSONException("Null key.");
212 | }
213 | if (this.mode == 'k') {
214 | try {
215 | JSONObject topObject = this.stack[this.top - 1];
216 | // don't use the built in putOnce method to maintain Android support
217 | if(topObject.has(string)) {
218 | throw new JSONException("Duplicate key \"" + string + "\"");
219 | }
220 | topObject.put(string, true);
221 | if (this.comma) {
222 | this.writer.append(',');
223 | }
224 | this.writer.append(JSONObject.quote(string));
225 | this.writer.append(':');
226 | this.comma = false;
227 | this.mode = 'o';
228 | return this;
229 | } catch (IOException e) {
230 | // Android as of API 25 does not support this exception constructor
231 | // however we won't worry about it. If an exception is happening here
232 | // it will just throw a "Method not found" exception instead.
233 | throw new JSONException(e);
234 | }
235 | }
236 | throw new JSONException("Misplaced key.");
237 | }
238 |
239 |
240 | /**
241 | * Begin appending a new object. All keys and values until the balancing
242 | * endObject will be appended to this object. The
243 | * endObject method must be called to mark the object's end.
244 | * @return this
245 | * @throws JSONException If the nesting is too deep, or if the object is
246 | * started in the wrong place (for example as a key or after the end of the
247 | * outermost array or object).
248 | */
249 | public JSONWriter object() throws JSONException {
250 | if (this.mode == 'i') {
251 | this.mode = 'o';
252 | }
253 | if (this.mode == 'o' || this.mode == 'a') {
254 | this.append("{");
255 | this.push(new JSONObject());
256 | this.comma = false;
257 | return this;
258 | }
259 | throw new JSONException("Misplaced object.");
260 |
261 | }
262 |
263 |
264 | /**
265 | * Pop an array or object scope.
266 | * @param c The scope to close.
267 | * @throws JSONException If nesting is wrong.
268 | */
269 | private void pop(char c) throws JSONException {
270 | if (this.top <= 0) {
271 | throw new JSONException("Nesting error.");
272 | }
273 | char m = this.stack[this.top - 1] == null ? 'a' : 'k';
274 | if (m != c) {
275 | throw new JSONException("Nesting error.");
276 | }
277 | this.top -= 1;
278 | this.mode = this.top == 0
279 | ? 'd'
280 | : this.stack[this.top - 1] == null
281 | ? 'a'
282 | : 'k';
283 | }
284 |
285 | /**
286 | * Push an array or object scope.
287 | * @param jo The scope to open.
288 | * @throws JSONException If nesting is too deep.
289 | */
290 | private void push(JSONObject jo) throws JSONException {
291 | if (this.top >= maxdepth) {
292 | throw new JSONException("Nesting too deep.");
293 | }
294 | this.stack[this.top] = jo;
295 | this.mode = jo == null ? 'a' : 'k';
296 | this.top += 1;
297 | }
298 |
299 | /**
300 | * Make a JSON text of an Object value. If the object has an
301 | * value.toJSONString() method, then that method will be used to produce the
302 | * JSON text. The method is required to produce a strictly conforming text.
303 | * If the object does not contain a toJSONString method (which is the most
304 | * common case), then a text will be produced by other means. If the value
305 | * is an array or Collection, then a JSONArray will be made from it and its
306 | * toJSONString method will be called. If the value is a MAP, then a
307 | * JSONObject will be made from it and its toJSONString method will be
308 | * called. Otherwise, the value's toString method will be called, and the
309 | * result will be quoted.
310 | *
311 | * { (left
318 | * brace) and ending with } (right
319 | * brace).
320 | * @throws JSONException
321 | * If the value is or contains an invalid number.
322 | */
323 | public static String valueToString(Object value) throws JSONException {
324 | if (value == null || value.equals(null)) {
325 | return "null";
326 | }
327 | if (value instanceof JSONString) {
328 | String object;
329 | try {
330 | object = ((JSONString) value).toJSONString();
331 | } catch (Exception e) {
332 | throw new JSONException(e);
333 | }
334 | if (object != null) {
335 | return object;
336 | }
337 | throw new JSONException("Bad value from toJSONString: " + object);
338 | }
339 | if (value instanceof Number) {
340 | // not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
341 | final String numberAsString = JSONObject.numberToString((Number) value);
342 | if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
343 | // Close enough to a JSON number that we will return it unquoted
344 | return numberAsString;
345 | }
346 | // The Number value is not a valid JSON number.
347 | // Instead we will quote it as a string
348 | return JSONObject.quote(numberAsString);
349 | }
350 | if (value instanceof Boolean || value instanceof JSONObject
351 | || value instanceof JSONArray) {
352 | return value.toString();
353 | }
354 | if (value instanceof Map) {
355 | Map, ?> map = (Map, ?>) value;
356 | return new JSONObject(map).toString();
357 | }
358 | if (value instanceof Collection) {
359 | Collection> coll = (Collection>) value;
360 | return new JSONArray(coll).toString();
361 | }
362 | if (value.getClass().isArray()) {
363 | return new JSONArray(value).toString();
364 | }
365 | if(value instanceof Enum>){
366 | return JSONObject.quote(((Enum>)value).name());
367 | }
368 | return JSONObject.quote(value.toString());
369 | }
370 |
371 | /**
372 | * Append either the value true or the value
373 | * false.
374 | * @param b A boolean.
375 | * @return this
376 | * @throws JSONException
377 | */
378 | public JSONWriter value(boolean b) throws JSONException {
379 | return this.append(b ? "true" : "false");
380 | }
381 |
382 | /**
383 | * Append a double value.
384 | * @param d A double.
385 | * @return this
386 | * @throws JSONException If the number is not finite.
387 | */
388 | public JSONWriter value(double d) throws JSONException {
389 | return this.value(Double.valueOf(d));
390 | }
391 |
392 | /**
393 | * Append a long value.
394 | * @param l A long.
395 | * @return this
396 | * @throws JSONException
397 | */
398 | public JSONWriter value(long l) throws JSONException {
399 | return this.append(Long.toString(l));
400 | }
401 |
402 |
403 | /**
404 | * Append an object value.
405 | * @param object The object to append. It can be null, or a Boolean, Number,
406 | * String, JSONObject, or JSONArray, or an object that implements JSONString.
407 | * @return this
408 | * @throws JSONException If the value is out of sequence.
409 | */
410 | public JSONWriter value(Object object) throws JSONException {
411 | return this.append(valueToString(object));
412 | }
413 | }
414 |
--------------------------------------------------------------------------------
/src/org/json/JSONTokener.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.io.Reader;
8 | import java.io.StringReader;
9 |
10 | /*
11 | Copyright (c) 2002 JSON.org
12 |
13 | Permission is hereby granted, free of charge, to any person obtaining a copy
14 | of this software and associated documentation files (the "Software"), to deal
15 | in the Software without restriction, including without limitation the rights
16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 | copies of the Software, and to permit persons to whom the Software is
18 | furnished to do so, subject to the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be included in all
21 | copies or substantial portions of the Software.
22 |
23 | The Software shall be used for Good, not Evil.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 | SOFTWARE.
32 | */
33 |
34 | /**
35 | * A JSONTokener takes a source string and extracts characters and tokens from
36 | * it. It is used by the JSONObject and JSONArray constructors to parse
37 | * JSON source strings.
38 | * @author JSON.org
39 | * @version 2014-05-03
40 | */
41 | public class JSONTokener {
42 | /** current read character position on the current line. */
43 | private long character;
44 | /** flag to indicate if the end of the input has been found. */
45 | private boolean eof;
46 | /** current read index of the input. */
47 | private long index;
48 | /** current line of the input. */
49 | private long line;
50 | /** previous character read from the input. */
51 | private char previous;
52 | /** Reader for the input. */
53 | private final Reader reader;
54 | /** flag to indicate that a previous character was requested. */
55 | private boolean usePrevious;
56 | /** the number of characters read in the previous line. */
57 | private long characterPreviousLine;
58 |
59 |
60 | /**
61 | * Construct a JSONTokener from a Reader. The caller must close the Reader.
62 | *
63 | * @param reader A reader.
64 | */
65 | public JSONTokener(Reader reader) {
66 | this.reader = reader.markSupported()
67 | ? reader
68 | : new BufferedReader(reader);
69 | this.eof = false;
70 | this.usePrevious = false;
71 | this.previous = 0;
72 | this.index = 0;
73 | this.character = 1;
74 | this.characterPreviousLine = 0;
75 | this.line = 1;
76 | }
77 |
78 |
79 | /**
80 | * Construct a JSONTokener from an InputStream. The caller must close the input stream.
81 | * @param inputStream The source.
82 | */
83 | public JSONTokener(InputStream inputStream) {
84 | this(new InputStreamReader(inputStream));
85 | }
86 |
87 |
88 | /**
89 | * Construct a JSONTokener from a string.
90 | *
91 | * @param s A source string.
92 | */
93 | public JSONTokener(String s) {
94 | this(new StringReader(s));
95 | }
96 |
97 |
98 | /**
99 | * Back up one character. This provides a sort of lookahead capability,
100 | * so that you can test for a digit or letter before attempting to parse
101 | * the next number or identifier.
102 | * @throws JSONException Thrown if trying to step back more than 1 step
103 | * or if already at the start of the string
104 | */
105 | public void back() throws JSONException {
106 | if (this.usePrevious || this.index <= 0) {
107 | throw new JSONException("Stepping back two steps is not supported");
108 | }
109 | this.decrementIndexes();
110 | this.usePrevious = true;
111 | this.eof = false;
112 | }
113 |
114 | /**
115 | * Decrements the indexes for the {@link #back()} method based on the previous character read.
116 | */
117 | private void decrementIndexes() {
118 | this.index--;
119 | if(this.previous=='\r' || this.previous == '\n') {
120 | this.line--;
121 | this.character=this.characterPreviousLine ;
122 | } else if(this.character > 0){
123 | this.character--;
124 | }
125 | }
126 |
127 | /**
128 | * Get the hex value of a character (base16).
129 | * @param c A character between '0' and '9' or between 'A' and 'F' or
130 | * between 'a' and 'f'.
131 | * @return An int between 0 and 15, or -1 if c was not a hex digit.
132 | */
133 | public static int dehexchar(char c) {
134 | if (c >= '0' && c <= '9') {
135 | return c - '0';
136 | }
137 | if (c >= 'A' && c <= 'F') {
138 | return c - ('A' - 10);
139 | }
140 | if (c >= 'a' && c <= 'f') {
141 | return c - ('a' - 10);
142 | }
143 | return -1;
144 | }
145 |
146 | /**
147 | * Checks if the end of the input has been reached.
148 | *
149 | * @return true if at the end of the file and we didn't step back
150 | */
151 | public boolean end() {
152 | return this.eof && !this.usePrevious;
153 | }
154 |
155 |
156 | /**
157 | * Determine if the source string still contains characters that next()
158 | * can consume.
159 | * @return true if not yet at the end of the source.
160 | * @throws JSONException thrown if there is an error stepping forward
161 | * or backward while checking for more data.
162 | */
163 | public boolean more() throws JSONException {
164 | if(this.usePrevious) {
165 | return true;
166 | }
167 | try {
168 | this.reader.mark(1);
169 | } catch (IOException e) {
170 | throw new JSONException("Unable to preserve stream position", e);
171 | }
172 | try {
173 | // -1 is EOF, but next() can not consume the null character '\0'
174 | if(this.reader.read() <= 0) {
175 | this.eof = true;
176 | return false;
177 | }
178 | this.reader.reset();
179 | } catch (IOException e) {
180 | throw new JSONException("Unable to read the next character from the stream", e);
181 | }
182 | return true;
183 | }
184 |
185 |
186 | /**
187 | * Get the next character in the source string.
188 | *
189 | * @return The next character, or 0 if past the end of the source string.
190 | * @throws JSONException Thrown if there is an error reading the source string.
191 | */
192 | public char next() throws JSONException {
193 | int c;
194 | if (this.usePrevious) {
195 | this.usePrevious = false;
196 | c = this.previous;
197 | } else {
198 | try {
199 | c = this.reader.read();
200 | } catch (IOException exception) {
201 | throw new JSONException(exception);
202 | }
203 | }
204 | if (c <= 0) { // End of stream
205 | this.eof = true;
206 | return 0;
207 | }
208 | this.incrementIndexes(c);
209 | this.previous = (char) c;
210 | return this.previous;
211 | }
212 |
213 | /**
214 | * Increments the internal indexes according to the previous character
215 | * read and the character passed as the current character.
216 | * @param c the current character read.
217 | */
218 | private void incrementIndexes(int c) {
219 | if(c > 0) {
220 | this.index++;
221 | if(c=='\r') {
222 | this.line++;
223 | this.characterPreviousLine = this.character;
224 | this.character=0;
225 | }else if (c=='\n') {
226 | if(this.previous != '\r') {
227 | this.line++;
228 | this.characterPreviousLine = this.character;
229 | }
230 | this.character=0;
231 | } else {
232 | this.character++;
233 | }
234 | }
235 | }
236 |
237 | /**
238 | * Consume the next character, and check that it matches a specified
239 | * character.
240 | * @param c The character to match.
241 | * @return The character.
242 | * @throws JSONException if the character does not match.
243 | */
244 | public char next(char c) throws JSONException {
245 | char n = this.next();
246 | if (n != c) {
247 | if(n > 0) {
248 | throw this.syntaxError("Expected '" + c + "' and instead saw '" +
249 | n + "'");
250 | }
251 | throw this.syntaxError("Expected '" + c + "' and instead saw ''");
252 | }
253 | return n;
254 | }
255 |
256 |
257 | /**
258 | * Get the next n characters.
259 | *
260 | * @param n The number of characters to take.
261 | * @return A string of n characters.
262 | * @throws JSONException
263 | * Substring bounds error if there are not
264 | * n characters remaining in the source string.
265 | */
266 | public String next(int n) throws JSONException {
267 | if (n == 0) {
268 | return "";
269 | }
270 |
271 | char[] chars = new char[n];
272 | int pos = 0;
273 |
274 | while (pos < n) {
275 | chars[pos] = this.next();
276 | if (this.end()) {
277 | throw this.syntaxError("Substring bounds error");
278 | }
279 | pos += 1;
280 | }
281 | return new String(chars);
282 | }
283 |
284 |
285 | /**
286 | * Get the next char in the string, skipping whitespace.
287 | * @throws JSONException Thrown if there is an error reading the source string.
288 | * @return A character, or 0 if there are no more characters.
289 | */
290 | public char nextClean() throws JSONException {
291 | for (;;) {
292 | char c = this.next();
293 | if (c == 0 || c > ' ') {
294 | return c;
295 | }
296 | }
297 | }
298 |
299 |
300 | /**
301 | * Return the characters up to the next close quote character.
302 | * Backslash processing is done. The formal JSON format does not
303 | * allow strings in single quotes, but an implementation is allowed to
304 | * accept them.
305 | * @param quote The quoting character, either
306 | * " (double quote) or
307 | * ' (single quote).
308 | * @return A String.
309 | * @throws JSONException Unterminated string.
310 | */
311 | public String nextString(char quote) throws JSONException {
312 | char c;
313 | StringBuilder sb = new StringBuilder();
314 | for (;;) {
315 | c = this.next();
316 | switch (c) {
317 | case 0:
318 | case '\n':
319 | case '\r':
320 | throw this.syntaxError("Unterminated string");
321 | case '\\':
322 | c = this.next();
323 | switch (c) {
324 | case 'b':
325 | sb.append('\b');
326 | break;
327 | case 't':
328 | sb.append('\t');
329 | break;
330 | case 'n':
331 | sb.append('\n');
332 | break;
333 | case 'f':
334 | sb.append('\f');
335 | break;
336 | case 'r':
337 | sb.append('\r');
338 | break;
339 | case 'u':
340 | try {
341 | sb.append((char)Integer.parseInt(this.next(4), 16));
342 | } catch (NumberFormatException e) {
343 | throw this.syntaxError("Illegal escape.", e);
344 | }
345 | break;
346 | case '"':
347 | case '\'':
348 | case '\\':
349 | case '/':
350 | sb.append(c);
351 | break;
352 | default:
353 | throw this.syntaxError("Illegal escape.");
354 | }
355 | break;
356 | default:
357 | if (c == quote) {
358 | return sb.toString();
359 | }
360 | sb.append(c);
361 | }
362 | }
363 | }
364 |
365 |
366 | /**
367 | * Get the text up but not including the specified character or the
368 | * end of line, whichever comes first.
369 | * @param delimiter A delimiter character.
370 | * @return A string.
371 | * @throws JSONException Thrown if there is an error while searching
372 | * for the delimiter
373 | */
374 | public String nextTo(char delimiter) throws JSONException {
375 | StringBuilder sb = new StringBuilder();
376 | for (;;) {
377 | char c = this.next();
378 | if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
379 | if (c != 0) {
380 | this.back();
381 | }
382 | return sb.toString().trim();
383 | }
384 | sb.append(c);
385 | }
386 | }
387 |
388 |
389 | /**
390 | * Get the text up but not including one of the specified delimiter
391 | * characters or the end of line, whichever comes first.
392 | * @param delimiters A set of delimiter characters.
393 | * @return A string, trimmed.
394 | * @throws JSONException Thrown if there is an error while searching
395 | * for the delimiter
396 | */
397 | public String nextTo(String delimiters) throws JSONException {
398 | char c;
399 | StringBuilder sb = new StringBuilder();
400 | for (;;) {
401 | c = this.next();
402 | if (delimiters.indexOf(c) >= 0 || c == 0 ||
403 | c == '\n' || c == '\r') {
404 | if (c != 0) {
405 | this.back();
406 | }
407 | return sb.toString().trim();
408 | }
409 | sb.append(c);
410 | }
411 | }
412 |
413 |
414 | /**
415 | * Get the next value. The value can be a Boolean, Double, Integer,
416 | * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
417 | * @throws JSONException If syntax error.
418 | *
419 | * @return An object.
420 | */
421 | public Object nextValue() throws JSONException {
422 | char c = this.nextClean();
423 | String string;
424 |
425 | switch (c) {
426 | case '"':
427 | case '\'':
428 | return this.nextString(c);
429 | case '{':
430 | this.back();
431 | return new JSONObject(this);
432 | case '[':
433 | this.back();
434 | return new JSONArray(this);
435 | }
436 |
437 | /*
438 | * Handle unquoted text. This could be the values true, false, or
439 | * null, or it can be a number. An implementation (such as this one)
440 | * is allowed to also accept non-standard forms.
441 | *
442 | * Accumulate characters until we reach the end of the text or a
443 | * formatting character.
444 | */
445 |
446 | StringBuilder sb = new StringBuilder();
447 | while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
448 | sb.append(c);
449 | c = this.next();
450 | }
451 | this.back();
452 |
453 | string = sb.toString().trim();
454 | if ("".equals(string)) {
455 | throw this.syntaxError("Missing value");
456 | }
457 | return JSONObject.stringToValue(string);
458 | }
459 |
460 |
461 | /**
462 | * Skip characters until the next character is the requested character.
463 | * If the requested character is not found, no characters are skipped.
464 | * @param to A character to skip to.
465 | * @return The requested character, or zero if the requested character
466 | * is not found.
467 | * @throws JSONException Thrown if there is an error while searching
468 | * for the to character
469 | */
470 | public char skipTo(char to) throws JSONException {
471 | char c;
472 | try {
473 | long startIndex = this.index;
474 | long startCharacter = this.character;
475 | long startLine = this.line;
476 | this.reader.mark(1000000);
477 | do {
478 | c = this.next();
479 | if (c == 0) {
480 | // in some readers, reset() may throw an exception if
481 | // the remaining portion of the input is greater than
482 | // the mark size (1,000,000 above).
483 | this.reader.reset();
484 | this.index = startIndex;
485 | this.character = startCharacter;
486 | this.line = startLine;
487 | return 0;
488 | }
489 | } while (c != to);
490 | this.reader.mark(1);
491 | } catch (IOException exception) {
492 | throw new JSONException(exception);
493 | }
494 | this.back();
495 | return c;
496 | }
497 |
498 | /**
499 | * Make a JSONException to signal a syntax error.
500 | *
501 | * @param message The error message.
502 | * @return A JSONException object, suitable for throwing
503 | */
504 | public JSONException syntaxError(String message) {
505 | return new JSONException(message + this.toString());
506 | }
507 |
508 | /**
509 | * Make a JSONException to signal a syntax error.
510 | *
511 | * @param message The error message.
512 | * @param causedBy The throwable that caused the error.
513 | * @return A JSONException object, suitable for throwing
514 | */
515 | public JSONException syntaxError(String message, Throwable causedBy) {
516 | return new JSONException(message + this.toString(), causedBy);
517 | }
518 |
519 | /**
520 | * Make a printable string of this JSONTokener.
521 | *
522 | * @return " at {index} [character {character} line {line}]"
523 | */
524 | @Override
525 | public String toString() {
526 | return " at " + this.index + " [character " + this.character + " line " +
527 | this.line + "]";
528 | }
529 | }
530 |
--------------------------------------------------------------------------------
/src/org/json/JSONML.java:
--------------------------------------------------------------------------------
1 | package org.json;
2 |
3 | /*
4 | Copyright (c) 2008 JSON.org
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | The Software shall be used for Good, not Evil.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | */
26 |
27 | /**
28 | * This provides static methods to convert an XML text into a JSONArray or
29 | * JSONObject, and to covert a JSONArray or JSONObject into an XML text using
30 | * the JsonML transform.
31 | *
32 | * @author JSON.org
33 | * @version 2016-01-30
34 | */
35 | public class JSONML {
36 | /**
37 | * Parse XML values and store them in a JSONArray.
38 | * @param x The XMLTokener containing the source string.
39 | * @param arrayForm true if array form, false if object form.
40 | * @param ja The JSONArray that is containing the current tag or null
41 | * if we are at the outermost level.
42 | * @param keepStrings Don't type-convert text nodes and attribute values
43 | * @return A JSONArray if the value is the outermost tag, otherwise null.
44 | * @throws JSONException
45 | */
46 | private static Object parse(
47 | XMLTokener x,
48 | boolean arrayForm,
49 | JSONArray ja,
50 | boolean keepStrings
51 | ) throws JSONException {
52 | String attribute;
53 | char c;
54 | String closeTag = null;
55 | int i;
56 | JSONArray newja = null;
57 | JSONObject newjo = null;
58 | Object token;
59 | String tagName = null;
60 |
61 | // Test for and skip past these forms:
62 | //
63 | //
64 | //
65 | // ... ?>
66 |
67 | while (true) {
68 | if (!x.more()) {
69 | throw x.syntaxError("Bad XML");
70 | }
71 | token = x.nextContent();
72 | if (token == XML.LT) {
73 | token = x.nextToken();
74 | if (token instanceof Character) {
75 | if (token == XML.SLASH) {
76 |
77 | // Close tag
78 |
79 | token = x.nextToken();
80 | if (!(token instanceof String)) {
81 | throw new JSONException(
82 | "Expected a closing name instead of '" +
83 | token + "'.");
84 | }
85 | if (x.nextToken() != XML.GT) {
86 | throw x.syntaxError("Misshaped close tag");
87 | }
88 | return token;
89 | } else if (token == XML.BANG) {
90 |
91 | // ");
97 | } else {
98 | x.back();
99 | }
100 | } else if (c == '[') {
101 | token = x.nextToken();
102 | if (token.equals("CDATA") && x.next() == '[') {
103 | if (ja != null) {
104 | ja.put(x.nextCDATA());
105 | }
106 | } else {
107 | throw x.syntaxError("Expected 'CDATA['");
108 | }
109 | } else {
110 | i = 1;
111 | do {
112 | token = x.nextMeta();
113 | if (token == null) {
114 | throw x.syntaxError("Missing '>' after ' 0);
121 | }
122 | } else if (token == XML.QUEST) {
123 |
124 | //
125 |
126 | x.skipPast("?>");
127 | } else {
128 | throw x.syntaxError("Misshaped tag");
129 | }
130 |
131 | // Open tag <
132 |
133 | } else {
134 | if (!(token instanceof String)) {
135 | throw x.syntaxError("Bad tagName '" + token + "'.");
136 | }
137 | tagName = (String)token;
138 | newja = new JSONArray();
139 | newjo = new JSONObject();
140 | if (arrayForm) {
141 | newja.put(tagName);
142 | if (ja != null) {
143 | ja.put(newja);
144 | }
145 | } else {
146 | newjo.put("tagName", tagName);
147 | if (ja != null) {
148 | ja.put(newjo);
149 | }
150 | }
151 | token = null;
152 | for (;;) {
153 | if (token == null) {
154 | token = x.nextToken();
155 | }
156 | if (token == null) {
157 | throw x.syntaxError("Misshaped tag");
158 | }
159 | if (!(token instanceof String)) {
160 | break;
161 | }
162 |
163 | // attribute = value
164 |
165 | attribute = (String)token;
166 | if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
167 | throw x.syntaxError("Reserved attribute.");
168 | }
169 | token = x.nextToken();
170 | if (token == XML.EQ) {
171 | token = x.nextToken();
172 | if (!(token instanceof String)) {
173 | throw x.syntaxError("Missing value");
174 | }
175 | newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
176 | token = null;
177 | } else {
178 | newjo.accumulate(attribute, "");
179 | }
180 | }
181 | if (arrayForm && newjo.length() > 0) {
182 | newja.put(newjo);
183 | }
184 |
185 | // Empty tag <.../>
186 |
187 | if (token == XML.SLASH) {
188 | if (x.nextToken() != XML.GT) {
189 | throw x.syntaxError("Misshaped tag");
190 | }
191 | if (ja == null) {
192 | if (arrayForm) {
193 | return newja;
194 | }
195 | return newjo;
196 | }
197 |
198 | // Content, between <...> and
199 |
200 | } else {
201 | if (token != XML.GT) {
202 | throw x.syntaxError("Misshaped tag");
203 | }
204 | closeTag = (String)parse(x, arrayForm, newja, keepStrings);
205 | if (closeTag != null) {
206 | if (!closeTag.equals(tagName)) {
207 | throw x.syntaxError("Mismatched '" + tagName +
208 | "' and '" + closeTag + "'");
209 | }
210 | tagName = null;
211 | if (!arrayForm && newja.length() > 0) {
212 | newjo.put("childNodes", newja);
213 | }
214 | if (ja == null) {
215 | if (arrayForm) {
216 | return newja;
217 | }
218 | return newjo;
219 | }
220 | }
221 | }
222 | }
223 | } else {
224 | if (ja != null) {
225 | ja.put(token instanceof String
226 | ? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
227 | : token);
228 | }
229 | }
230 | }
231 | }
232 |
233 |
234 | /**
235 | * Convert a well-formed (but not necessarily valid) XML string into a
236 | * JSONArray using the JsonML transform. Each XML tag is represented as
237 | * a JSONArray in which the first element is the tag name. If the tag has
238 | * attributes, then the second element will be JSONObject containing the
239 | * name/value pairs. If the tag contains children, then strings and
240 | * JSONArrays will represent the child tags.
241 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
242 | * @param string The source string.
243 | * @return A JSONArray containing the structured data from the XML string.
244 | * @throws JSONException Thrown on error converting to a JSONArray
245 | */
246 | public static JSONArray toJSONArray(String string) throws JSONException {
247 | return (JSONArray)parse(new XMLTokener(string), true, null, false);
248 | }
249 |
250 |
251 | /**
252 | * Convert a well-formed (but not necessarily valid) XML string into a
253 | * JSONArray using the JsonML transform. Each XML tag is represented as
254 | * a JSONArray in which the first element is the tag name. If the tag has
255 | * attributes, then the second element will be JSONObject containing the
256 | * name/value pairs. If the tag contains children, then strings and
257 | * JSONArrays will represent the child tags.
258 | * As opposed to toJSONArray this method does not attempt to convert
259 | * any text node or attribute value to any type
260 | * but just leaves it as a string.
261 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
262 | * @param string The source string.
263 | * @param keepStrings If true, then values will not be coerced into boolean
264 | * or numeric values and will instead be left as strings
265 | * @return A JSONArray containing the structured data from the XML string.
266 | * @throws JSONException Thrown on error converting to a JSONArray
267 | */
268 | public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
269 | return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
270 | }
271 |
272 |
273 | /**
274 | * Convert a well-formed (but not necessarily valid) XML string into a
275 | * JSONArray using the JsonML transform. Each XML tag is represented as
276 | * a JSONArray in which the first element is the tag name. If the tag has
277 | * attributes, then the second element will be JSONObject containing the
278 | * name/value pairs. If the tag contains children, then strings and
279 | * JSONArrays will represent the child content and tags.
280 | * As opposed to toJSONArray this method does not attempt to convert
281 | * any text node or attribute value to any type
282 | * but just leaves it as a string.
283 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
284 | * @param x An XMLTokener.
285 | * @param keepStrings If true, then values will not be coerced into boolean
286 | * or numeric values and will instead be left as strings
287 | * @return A JSONArray containing the structured data from the XML string.
288 | * @throws JSONException Thrown on error converting to a JSONArray
289 | */
290 | public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
291 | return (JSONArray)parse(x, true, null, keepStrings);
292 | }
293 |
294 |
295 | /**
296 | * Convert a well-formed (but not necessarily valid) XML string into a
297 | * JSONArray using the JsonML transform. Each XML tag is represented as
298 | * a JSONArray in which the first element is the tag name. If the tag has
299 | * attributes, then the second element will be JSONObject containing the
300 | * name/value pairs. If the tag contains children, then strings and
301 | * JSONArrays will represent the child content and tags.
302 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
303 | * @param x An XMLTokener.
304 | * @return A JSONArray containing the structured data from the XML string.
305 | * @throws JSONException Thrown on error converting to a JSONArray
306 | */
307 | public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
308 | return (JSONArray)parse(x, true, null, false);
309 | }
310 |
311 |
312 | /**
313 | * Convert a well-formed (but not necessarily valid) XML string into a
314 | * JSONObject using the JsonML transform. Each XML tag is represented as
315 | * a JSONObject with a "tagName" property. If the tag has attributes, then
316 | * the attributes will be in the JSONObject as properties. If the tag
317 | * contains children, the object will have a "childNodes" property which
318 | * will be an array of strings and JsonML JSONObjects.
319 |
320 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
321 | * @param string The XML source text.
322 | * @return A JSONObject containing the structured data from the XML string.
323 | * @throws JSONException Thrown on error converting to a JSONObject
324 | */
325 | public static JSONObject toJSONObject(String string) throws JSONException {
326 | return (JSONObject)parse(new XMLTokener(string), false, null, false);
327 | }
328 |
329 |
330 | /**
331 | * Convert a well-formed (but not necessarily valid) XML string into a
332 | * JSONObject using the JsonML transform. Each XML tag is represented as
333 | * a JSONObject with a "tagName" property. If the tag has attributes, then
334 | * the attributes will be in the JSONObject as properties. If the tag
335 | * contains children, the object will have a "childNodes" property which
336 | * will be an array of strings and JsonML JSONObjects.
337 |
338 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
339 | * @param string The XML source text.
340 | * @param keepStrings If true, then values will not be coerced into boolean
341 | * or numeric values and will instead be left as strings
342 | * @return A JSONObject containing the structured data from the XML string.
343 | * @throws JSONException Thrown on error converting to a JSONObject
344 | */
345 | public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
346 | return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
347 | }
348 |
349 |
350 | /**
351 | * Convert a well-formed (but not necessarily valid) XML string into a
352 | * JSONObject using the JsonML transform. Each XML tag is represented as
353 | * a JSONObject with a "tagName" property. If the tag has attributes, then
354 | * the attributes will be in the JSONObject as properties. If the tag
355 | * contains children, the object will have a "childNodes" property which
356 | * will be an array of strings and JsonML JSONObjects.
357 |
358 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
359 | * @param x An XMLTokener of the XML source text.
360 | * @return A JSONObject containing the structured data from the XML string.
361 | * @throws JSONException Thrown on error converting to a JSONObject
362 | */
363 | public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
364 | return (JSONObject)parse(x, false, null, false);
365 | }
366 |
367 |
368 | /**
369 | * Convert a well-formed (but not necessarily valid) XML string into a
370 | * JSONObject using the JsonML transform. Each XML tag is represented as
371 | * a JSONObject with a "tagName" property. If the tag has attributes, then
372 | * the attributes will be in the JSONObject as properties. If the tag
373 | * contains children, the object will have a "childNodes" property which
374 | * will be an array of strings and JsonML JSONObjects.
375 |
376 | * Comments, prologs, DTDs, and <[ [ ]]> are ignored.
377 | * @param x An XMLTokener of the XML source text.
378 | * @param keepStrings If true, then values will not be coerced into boolean
379 | * or numeric values and will instead be left as strings
380 | * @return A JSONObject containing the structured data from the XML string.
381 | * @throws JSONException Thrown on error converting to a JSONObject
382 | */
383 | public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
384 | return (JSONObject)parse(x, false, null, keepStrings);
385 | }
386 |
387 |
388 | /**
389 | * Reverse the JSONML transformation, making an XML text from a JSONArray.
390 | * @param ja A JSONArray.
391 | * @return An XML string.
392 | * @throws JSONException Thrown on error converting to a string
393 | */
394 | public static String toString(JSONArray ja) throws JSONException {
395 | int i;
396 | JSONObject jo;
397 | int length;
398 | Object object;
399 | StringBuilder sb = new StringBuilder();
400 | String tagName;
401 |
402 | // Emit
71 | * string.codePoints()
72 | *
73 | * which is available in Java8 and above.
74 | *
75 | * @see http://stackoverflow.com/a/21791059/6030888
77 | */
78 | private static Iterable
111 | * & (ampersand) is replaced by &
112 | * < (less than) is replaced by <
113 | * > (greater than) is replaced by >
114 | * " (double quote) is replaced by "
115 | * ' (single quote / apostrophe) is replaced by '
116 | *
117 | *
118 | * @param string
119 | * The string to be escaped.
120 | * @return The escaped string.
121 | */
122 | public static String escape(String string) {
123 | StringBuilder sb = new StringBuilder(string.length());
124 | for (final int cp : codePointIterator(string)) {
125 | switch (cp) {
126 | case '&':
127 | sb.append("&");
128 | break;
129 | case '<':
130 | sb.append("<");
131 | break;
132 | case '>':
133 | sb.append(">");
134 | break;
135 | case '"':
136 | sb.append(""");
137 | break;
138 | case '\'':
139 | sb.append("'");
140 | break;
141 | default:
142 | if (mustEscape(cp)) {
143 | sb.append("");
144 | sb.append(Integer.toHexString(cp));
145 | sb.append(';');
146 | } else {
147 | sb.appendCodePoint(cp);
148 | }
149 | }
150 | }
151 | return sb.toString();
152 | }
153 |
154 | /**
155 | * @param cp code point to test
156 | * @return true if the code point is not valid for an XML
157 | */
158 | private static boolean mustEscape(int cp) {
159 | /* Valid range from https://www.w3.org/TR/REC-xml/#charsets
160 | *
161 | * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
162 | *
163 | * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
164 | */
165 | // isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
166 | // all ISO control characters are out of range except tabs and new lines
167 | return (Character.isISOControl(cp)
168 | && cp != 0x9
169 | && cp != 0xA
170 | && cp != 0xD
171 | ) || !(
172 | // valid the range of acceptable characters that aren't control
173 | (cp >= 0x20 && cp <= 0xD7FF)
174 | || (cp >= 0xE000 && cp <= 0xFFFD)
175 | || (cp >= 0x10000 && cp <= 0x10FFFF)
176 | )
177 | ;
178 | }
179 |
180 | /**
181 | * Removes XML escapes from the string.
182 | *
183 | * @param string
184 | * string to remove escapes from
185 | * @return string with converted entities
186 | */
187 | public static String unescape(String string) {
188 | StringBuilder sb = new StringBuilder(string.length());
189 | for (int i = 0, length = string.length(); i < length; i++) {
190 | char c = string.charAt(i);
191 | if (c == '&') {
192 | final int semic = string.indexOf(';', i);
193 | if (semic > i) {
194 | final String entity = string.substring(i + 1, semic);
195 | sb.append(XMLTokener.unescapeEntity(entity));
196 | // skip past the entity we just parsed.
197 | i += entity.length() + 1;
198 | } else {
199 | // this shouldn't happen in most cases since the parser
200 | // errors on unclosed entries.
201 | sb.append(c);
202 | }
203 | } else {
204 | // not part of an entity
205 | sb.append(c);
206 | }
207 | }
208 | return sb.toString();
209 | }
210 |
211 | /**
212 | * Throw an exception if the string contains whitespace. Whitespace is not
213 | * allowed in tagNames and attributes.
214 | *
215 | * @param string
216 | * A string.
217 | * @throws JSONException Thrown if the string contains whitespace or is empty.
218 | */
219 | public static void noSpace(String string) throws JSONException {
220 | int i, length = string.length();
221 | if (length == 0) {
222 | throw new JSONException("Empty string.");
223 | }
224 | for (i = 0; i < length; i += 1) {
225 | if (Character.isWhitespace(string.charAt(i))) {
226 | throw new JSONException("'" + string
227 | + "' contains a space character.");
228 | }
229 | }
230 | }
231 |
232 | /**
233 | * Scan the content following the named tag, attaching it to the context.
234 | *
235 | * @param x
236 | * The XMLTokener containing the source string.
237 | * @param context
238 | * The JSONObject that will include the new material.
239 | * @param name
240 | * The tag name.
241 | * @return true if the close tag is processed.
242 | * @throws JSONException
243 | */
244 | private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings)
245 | throws JSONException {
246 | char c;
247 | int i;
248 | JSONObject jsonobject = null;
249 | String string;
250 | String tagName;
251 | Object token;
252 |
253 | // Test for and skip past these forms:
254 | //
255 | //
256 | //
257 | // ... ?>
258 | // Report errors for these forms:
259 | // <>
260 | // <=
261 | // <<
262 |
263 | token = x.nextToken();
264 |
265 | // ");
272 | return false;
273 | }
274 | x.back();
275 | } else if (c == '[') {
276 | token = x.nextToken();
277 | if ("CDATA".equals(token)) {
278 | if (x.next() == '[') {
279 | string = x.nextCDATA();
280 | if (string.length() > 0) {
281 | context.accumulate("content", string);
282 | }
283 | return false;
284 | }
285 | }
286 | throw x.syntaxError("Expected 'CDATA['");
287 | }
288 | i = 1;
289 | do {
290 | token = x.nextMeta();
291 | if (token == null) {
292 | throw x.syntaxError("Missing '>' after ' 0);
299 | return false;
300 | } else if (token == QUEST) {
301 |
302 | //
303 | x.skipPast("?>");
304 | return false;
305 | } else if (token == SLASH) {
306 |
307 | // Close tag
308 |
309 | token = x.nextToken();
310 | if (name == null) {
311 | throw x.syntaxError("Mismatched close tag " + token);
312 | }
313 | if (!token.equals(name)) {
314 | throw x.syntaxError("Mismatched " + name + " and " + token);
315 | }
316 | if (x.nextToken() != GT) {
317 | throw x.syntaxError("Misshaped close tag");
318 | }
319 | return true;
320 |
321 | } else if (token instanceof Character) {
322 | throw x.syntaxError("Misshaped tag");
323 |
324 | // Open tag <
325 |
326 | } else {
327 | tagName = (String) token;
328 | token = null;
329 | jsonobject = new JSONObject();
330 | for (;;) {
331 | if (token == null) {
332 | token = x.nextToken();
333 | }
334 | // attribute = value
335 | if (token instanceof String) {
336 | string = (String) token;
337 | token = x.nextToken();
338 | if (token == EQ) {
339 | token = x.nextToken();
340 | if (!(token instanceof String)) {
341 | throw x.syntaxError("Missing value");
342 | }
343 | jsonobject.accumulate(string,
344 | keepStrings ? ((String)token) : stringToValue((String) token));
345 | token = null;
346 | } else {
347 | jsonobject.accumulate(string, "");
348 | }
349 |
350 |
351 | } else if (token == SLASH) {
352 | // Empty tag <.../>
353 | if (x.nextToken() != GT) {
354 | throw x.syntaxError("Misshaped tag");
355 | }
356 | if (jsonobject.length() > 0) {
357 | context.accumulate(tagName, jsonobject);
358 | } else {
359 | context.accumulate(tagName, "");
360 | }
361 | return false;
362 |
363 | } else if (token == GT) {
364 | // Content, between <...> and
365 | for (;;) {
366 | token = x.nextContent();
367 | if (token == null) {
368 | if (tagName != null) {
369 | throw x.syntaxError("Unclosed tag " + tagName);
370 | }
371 | return false;
372 | } else if (token instanceof String) {
373 | string = (String) token;
374 | if (string.length() > 0) {
375 | jsonobject.accumulate("content",
376 | keepStrings ? string : stringToValue(string));
377 | }
378 |
379 | } else if (token == LT) {
380 | // Nested element
381 | if (parse(x, jsonobject, tagName,keepStrings)) {
382 | if (jsonobject.length() == 0) {
383 | context.accumulate(tagName, "");
384 | } else if (jsonobject.length() == 1
385 | && jsonobject.opt("content") != null) {
386 | context.accumulate(tagName,
387 | jsonobject.opt("content"));
388 | } else {
389 | context.accumulate(tagName, jsonobject);
390 | }
391 | return false;
392 | }
393 | }
394 | }
395 | } else {
396 | throw x.syntaxError("Misshaped tag");
397 | }
398 | }
399 | }
400 | }
401 |
402 | /**
403 | * This method is the same as {@link JSONObject#stringToValue(String)}.
404 | *
405 | * @param string String to convert
406 | * @return JSON value of this string or the string
407 | */
408 | // To maintain compatibility with the Android API, this method is a direct copy of
409 | // the one in JSONObject. Changes made here should be reflected there.
410 | public static Object stringToValue(String string) {
411 | if (string.equals("")) {
412 | return string;
413 | }
414 | if (string.equalsIgnoreCase("true")) {
415 | return Boolean.TRUE;
416 | }
417 | if (string.equalsIgnoreCase("false")) {
418 | return Boolean.FALSE;
419 | }
420 | if (string.equalsIgnoreCase("null")) {
421 | return JSONObject.NULL;
422 | }
423 |
424 | /*
425 | * If it might be a number, try converting it. If a number cannot be
426 | * produced, then the value will just be a string.
427 | */
428 |
429 | char initial = string.charAt(0);
430 | if ((initial >= '0' && initial <= '9') || initial == '-') {
431 | try {
432 | // if we want full Big Number support this block can be replaced with:
433 | // return stringToNumber(string);
434 | if (string.indexOf('.') > -1 || string.indexOf('e') > -1
435 | || string.indexOf('E') > -1 || "-0".equals(string)) {
436 | Double d = Double.valueOf(string);
437 | if (!d.isInfinite() && !d.isNaN()) {
438 | return d;
439 | }
440 | } else {
441 | Long myLong = Long.valueOf(string);
442 | if (string.equals(myLong.toString())) {
443 | if (myLong.longValue() == myLong.intValue()) {
444 | return Integer.valueOf(myLong.intValue());
445 | }
446 | return myLong;
447 | }
448 | }
449 | } catch (Exception ignore) {
450 | }
451 | }
452 | return string;
453 | }
454 |
455 | /**
456 | * Convert a well-formed (but not necessarily valid) XML string into a
457 | * JSONObject. Some information may be lost in this transformation because
458 | * JSON is a data format and XML is a document format. XML uses elements,
459 | * attributes, and content text, while JSON uses unordered collections of
460 | * name/value pairs and arrays of values. JSON does not does not like to
461 | * distinguish between elements and attributes. Sequences of similar
462 | * elements are represented as JSONArrays. Content text may be placed in a
463 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
464 | * are ignored.
465 | *
466 | * @param string
467 | * The source string.
468 | * @return A JSONObject containing the structured data from the XML string.
469 | * @throws JSONException Thrown if there is an errors while parsing the string
470 | */
471 | public static JSONObject toJSONObject(String string) throws JSONException {
472 | return toJSONObject(string, false);
473 | }
474 |
475 | /**
476 | * Convert a well-formed (but not necessarily valid) XML into a
477 | * JSONObject. Some information may be lost in this transformation because
478 | * JSON is a data format and XML is a document format. XML uses elements,
479 | * attributes, and content text, while JSON uses unordered collections of
480 | * name/value pairs and arrays of values. JSON does not does not like to
481 | * distinguish between elements and attributes. Sequences of similar
482 | * elements are represented as JSONArrays. Content text may be placed in a
483 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
484 | * are ignored.
485 | *
486 | * @param reader The XML source reader.
487 | * @return A JSONObject containing the structured data from the XML string.
488 | * @throws JSONException Thrown if there is an errors while parsing the string
489 | */
490 | public static JSONObject toJSONObject(Reader reader) throws JSONException {
491 | return toJSONObject(reader, false);
492 | }
493 |
494 | /**
495 | * Convert a well-formed (but not necessarily valid) XML into a
496 | * JSONObject. Some information may be lost in this transformation because
497 | * JSON is a data format and XML is a document format. XML uses elements,
498 | * attributes, and content text, while JSON uses unordered collections of
499 | * name/value pairs and arrays of values. JSON does not does not like to
500 | * distinguish between elements and attributes. Sequences of similar
501 | * elements are represented as JSONArrays. Content text may be placed in a
502 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
503 | * are ignored.
504 | *
505 | * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
506 | * numbers but will instead be the exact value as seen in the XML document.
507 | *
508 | * @param reader The XML source reader.
509 | * @param keepStrings If true, then values will not be coerced into boolean
510 | * or numeric values and will instead be left as strings
511 | * @return A JSONObject containing the structured data from the XML string.
512 | * @throws JSONException Thrown if there is an errors while parsing the string
513 | */
514 | public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException {
515 | JSONObject jo = new JSONObject();
516 | XMLTokener x = new XMLTokener(reader);
517 | while (x.more()) {
518 | x.skipPast("<");
519 | if(x.more()) {
520 | parse(x, jo, null, keepStrings);
521 | }
522 | }
523 | return jo;
524 | }
525 |
526 | /**
527 | * Convert a well-formed (but not necessarily valid) XML string into a
528 | * JSONObject. Some information may be lost in this transformation because
529 | * JSON is a data format and XML is a document format. XML uses elements,
530 | * attributes, and content text, while JSON uses unordered collections of
531 | * name/value pairs and arrays of values. JSON does not does not like to
532 | * distinguish between elements and attributes. Sequences of similar
533 | * elements are represented as JSONArrays. Content text may be placed in a
534 | * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
535 | * are ignored.
536 | *
537 | * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
538 | * numbers but will instead be the exact value as seen in the XML document.
539 | *
540 | * @param string
541 | * The source string.
542 | * @param keepStrings If true, then values will not be coerced into boolean
543 | * or numeric values and will instead be left as strings
544 | * @return A JSONObject containing the structured data from the XML string.
545 | * @throws JSONException Thrown if there is an errors while parsing the string
546 | */
547 | public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
548 | return toJSONObject(new StringReader(string), keepStrings);
549 | }
550 |
551 | /**
552 | * Convert a JSONObject into a well-formed, element-normal XML string.
553 | *
554 | * @param object
555 | * A JSONObject.
556 | * @return A string.
557 | * @throws JSONException Thrown if there is an error parsing the string
558 | */
559 | public static String toString(Object object) throws JSONException {
560 | return toString(object, null);
561 | }
562 |
563 | /**
564 | * Convert a JSONObject into a well-formed, element-normal XML string.
565 | *
566 | * @param object
567 | * A JSONObject.
568 | * @param tagName
569 | * The optional name of the enclosing tag.
570 | * @return A string.
571 | * @throws JSONException Thrown if there is an error parsing the string
572 | */
573 | public static String toString(final Object object, final String tagName)
574 | throws JSONException {
575 | StringBuilder sb = new StringBuilder();
576 | JSONArray ja;
577 | JSONObject jo;
578 | String string;
579 |
580 | if (object instanceof JSONObject) {
581 |
582 | // Emit