golf 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/golf.gemspec +1 -1
- data/lib/golf/version.rb +1 -1
- metadata +1 -121
- data/golf-java/README.markdown +0 -41
- data/golf-java/THANKS.markdown +0 -14
- data/golf-java/build/classes.zip +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfResource$MimeMapping$MimeMappingSingleton.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfResource$MimeMapping.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfResource.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$1.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$GolfContext.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$GolfParams.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$GolfSession.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$PermanentRedirectException.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$RedirectException.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet$StoredJSVM.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/GolfServlet.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/JsonpTunnel.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/Main$1.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/Main$RingList.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/Main.class +0 -0
- data/golf-java/build/com/thinkminimo/golf/ProxyServlet.class +0 -0
- data/golf-java/build/com/yahoo/platform/yui/compressor/CssCompressor.class +0 -0
- data/golf-java/build/com/yahoo/platform/yui/compressor/JarClassLoader.class +0 -0
- data/golf-java/build/com/yahoo/platform/yui/compressor/JavaScriptCompressor.class +0 -0
- data/golf-java/build/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.class +0 -0
- data/golf-java/build/com/yahoo/platform/yui/compressor/JavaScriptToken.class +0 -0
- data/golf-java/build/com/yahoo/platform/yui/compressor/ScriptOrFnScope.class +0 -0
- data/golf-java/build/depends.zip +0 -0
- data/golf-java/build/golf +0 -2
- data/golf-java/build/org/json/JSONArray.class +0 -0
- data/golf-java/build/org/json/JSONException.class +0 -0
- data/golf-java/build/org/json/JSONObject$1.class +0 -0
- data/golf-java/build/org/json/JSONObject$Null.class +0 -0
- data/golf-java/build/org/json/JSONObject.class +0 -0
- data/golf-java/build/org/json/JSONString.class +0 -0
- data/golf-java/build/org/json/JSONStringer.class +0 -0
- data/golf-java/build/org/json/JSONTokener.class +0 -0
- data/golf-java/build/org/json/JSONWriter.class +0 -0
- data/golf-java/build/resources.zip +0 -0
- data/golf-java/build.xml +0 -174
- data/golf-java/dist/golf.zip +0 -0
- data/golf-java/lib/ant-launcher.jar +0 -0
- data/golf-java/lib/ant.jar +0 -0
- data/golf-java/lib/commons-codec-1.4.jar +0 -0
- data/golf-java/lib/commons-collections-3.2.1.jar +0 -0
- data/golf-java/lib/commons-fileupload-1.2.1.jar +0 -0
- data/golf-java/lib/commons-httpclient-3.1.jar +0 -0
- data/golf-java/lib/commons-io-1.4.jar +0 -0
- data/golf-java/lib/commons-lang-2.4.jar +0 -0
- data/golf-java/lib/commons-logging-1.1.1.jar +0 -0
- data/golf-java/lib/cssparser-0.9.5.jar +0 -0
- data/golf-java/lib/getopt-0.1-dev.jar +0 -0
- data/golf-java/lib/htmlunit-2.6.jar +0 -0
- data/golf-java/lib/htmlunit-core-js-2.6.jar +0 -0
- data/golf-java/lib/java-xmlbuilder-1.jar +0 -0
- data/golf-java/lib/jets3t-0.7.0.jar +0 -0
- data/golf-java/lib/jetty-6.1.15.jar +0 -0
- data/golf-java/lib/jetty-util-6.1.15.jar +0 -0
- data/golf-java/lib/log4j-1.2.15.jar +0 -0
- data/golf-java/lib/nekohtml-1.9.13.jar +0 -0
- data/golf-java/lib/sac-1.3.jar +0 -0
- data/golf-java/lib/serializer-2.7.1.jar +0 -0
- data/golf-java/lib/servlet-api-2.5-20081211.jar +0 -0
- data/golf-java/lib/xalan-2.7.1.jar +0 -0
- data/golf-java/lib/xercesImpl-2.9.1.jar +0 -0
- data/golf-java/lib/xml-apis-1.3.04.jar +0 -0
- data/golf-java/resources/app_error.html +0 -60
- data/golf-java/resources/error.html +0 -29
- data/golf-java/resources/forcebot.txt +0 -0
- data/golf-java/resources/forceclient.txt +0 -0
- data/golf-java/resources/forceproxy.txt +0 -0
- data/golf-java/resources/head.html +0 -0
- data/golf-java/resources/jquery.address.js +0 -439
- data/golf-java/resources/jquery.golf.js +0 -945
- data/golf-java/resources/jquery.js +0 -4376
- data/golf-java/resources/jsdetect.html +0 -23
- data/golf-java/resources/loading.gif +0 -0
- data/golf-java/resources/new.html +0 -45
- data/golf-java/resources/new.static.html +0 -45
- data/golf-java/resources/noscript.forceclient.html +0 -11
- data/golf-java/resources/noscript.html +0 -18
- data/golf-java/resources/noscript.static.html +0 -15
- data/golf-java/resources/project.xml +0 -21
- data/golf-java/resources/proxy_project.xml +0 -11
- data/golf-java/resources/proxy_web.xml +0 -40
- data/golf-java/resources/static_project.xml +0 -37
- data/golf-java/resources/version +0 -1
- data/golf-java/resources/web.xml +0 -36
- data/golf-java/resources/welcome2golf.html +0 -50
- data/golf-java/src/com/thinkminimo/golf/GolfResource.java +0 -582
- data/golf-java/src/com/thinkminimo/golf/GolfServlet.java +0 -1055
- data/golf-java/src/com/thinkminimo/golf/JsonpTunnel.java +0 -86
- data/golf-java/src/com/thinkminimo/golf/Main.java +0 -1299
- data/golf-java/src/com/thinkminimo/golf/ProxyServlet.java +0 -577
- data/golf-java/src/com/yahoo/platform/yui/compressor/CssCompressor.java +0 -188
- data/golf-java/src/com/yahoo/platform/yui/compressor/JarClassLoader.java +0 -158
- data/golf-java/src/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java +0 -1281
- data/golf-java/src/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java +0 -55
- data/golf-java/src/com/yahoo/platform/yui/compressor/JavaScriptToken.java +0 -28
- data/golf-java/src/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java +0 -160
- data/golf-java/src/org/json/JSONArray.java +0 -934
- data/golf-java/src/org/json/JSONException.java +0 -27
- data/golf-java/src/org/json/JSONObject.java +0 -1550
- data/golf-java/src/org/json/JSONString.java +0 -18
- data/golf-java/src/org/json/JSONStringer.java +0 -78
- data/golf-java/src/org/json/JSONTokener.java +0 -422
- data/golf-java/src/org/json/JSONWriter.java +0 -323
- data/golf-java/test/client/golftest/README.markdown +0 -3
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.css +0 -114
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.html +0 -17
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.js +0 -81
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.res/asc.gif +0 -0
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.res/bg.gif +0 -0
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.res/desc.gif +0 -0
- data/golf-java/test/client/golftest/components/com/thinkminimo/golf/test/Harness.res/test/test.html +0 -1
- data/golf-java/test/client/golftest/controller.js +0 -131
- data/golf-java/test/client/golftest/forceclient.txt +0 -0
- data/golf-java/test/client/golftest/forceproxy.txt +0 -0
- data/golf-java/test/client/golftest/head.html +0 -1
- data/golf-java/test/client/golftest/scripts/jquery.tablesort.js +0 -75
- data/golf-java/test/client/golftest/styles/style.css +0 -18
- data/golf-java/test/client/golftest/test/test.html +0 -1
|
@@ -1,1055 +0,0 @@
|
|
|
1
|
-
package com.thinkminimo.golf;
|
|
2
|
-
|
|
3
|
-
import org.json.JSONStringer;
|
|
4
|
-
import org.json.JSONException;
|
|
5
|
-
|
|
6
|
-
import java.io.*;
|
|
7
|
-
import java.util.concurrent.ConcurrentHashMap;
|
|
8
|
-
import java.util.concurrent.atomic.AtomicBoolean;
|
|
9
|
-
import java.util.*;
|
|
10
|
-
import java.util.regex.Pattern;
|
|
11
|
-
import net.sourceforge.htmlunit.corejs.javascript.*;
|
|
12
|
-
|
|
13
|
-
import java.net.*;
|
|
14
|
-
|
|
15
|
-
import javax.servlet.*;
|
|
16
|
-
import javax.servlet.http.*;
|
|
17
|
-
|
|
18
|
-
import org.mortbay.jetty.servlet.DefaultServlet;
|
|
19
|
-
|
|
20
|
-
import com.gargoylesoftware.htmlunit.*;
|
|
21
|
-
import com.gargoylesoftware.htmlunit.html.*;
|
|
22
|
-
import com.gargoylesoftware.htmlunit.xml.*;
|
|
23
|
-
import com.gargoylesoftware.htmlunit.javascript.*;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Golf servlet class!
|
|
27
|
-
*/
|
|
28
|
-
public class GolfServlet extends HttpServlet {
|
|
29
|
-
|
|
30
|
-
public static final int LOG_ALL = 0;
|
|
31
|
-
public static final int LOG_TRACE = 1;
|
|
32
|
-
public static final int LOG_DEBUG = 2;
|
|
33
|
-
public static final int LOG_INFO = 3;
|
|
34
|
-
public static final int LOG_WARN = 4;
|
|
35
|
-
public static final int LOG_ERROR = 5;
|
|
36
|
-
public static final int LOG_FATAL = 6;
|
|
37
|
-
public static final int LOG_NONE = 999;
|
|
38
|
-
|
|
39
|
-
public static final int JSVM_TIMEOUT = 10000;
|
|
40
|
-
|
|
41
|
-
private class StoredJSVM {
|
|
42
|
-
public WebClient client;
|
|
43
|
-
public HtmlPage lastPage;
|
|
44
|
-
public long lastAccessTime;
|
|
45
|
-
|
|
46
|
-
StoredJSVM(WebClient client) {
|
|
47
|
-
this.client = client;
|
|
48
|
-
this.lastPage = null;
|
|
49
|
-
this.lastAccessTime = (new Date()).getTime();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public static class RedirectException extends Exception {
|
|
54
|
-
public RedirectException(String msg) {
|
|
55
|
-
super(msg);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public static class PermanentRedirectException extends RedirectException {
|
|
60
|
-
public PermanentRedirectException(String msg) {
|
|
61
|
-
super(msg);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private class GolfSession {
|
|
66
|
-
private HttpSession mSess;
|
|
67
|
-
|
|
68
|
-
public GolfSession(HttpServletRequest req) {
|
|
69
|
-
mSess = req.getSession(true);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private String get(String name) {
|
|
73
|
-
return (String) mSess.getAttribute(name);
|
|
74
|
-
}
|
|
75
|
-
private void set(String name, String value) {
|
|
76
|
-
mSess.setAttribute(name, value);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public Integer getSeq() {
|
|
80
|
-
try {
|
|
81
|
-
return Integer.parseInt(get("golf"));
|
|
82
|
-
} catch (NumberFormatException e) { }
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
public void setSeq(Integer value) {
|
|
86
|
-
set("golf", String.valueOf(value));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
public Boolean getJs() {
|
|
90
|
-
return get("js") == null ? null : Boolean.parseBoolean(get("js"));
|
|
91
|
-
}
|
|
92
|
-
public void setJs(boolean value) {
|
|
93
|
-
set("js", String.valueOf(value));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
public String getIpAddr() {
|
|
97
|
-
return get("ipaddr");
|
|
98
|
-
}
|
|
99
|
-
public void setIpAddr(String value) {
|
|
100
|
-
set("ipaddr", value);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
public String getLastUrl() {
|
|
104
|
-
return get("lasturl");
|
|
105
|
-
}
|
|
106
|
-
public void setLastUrl(String value) {
|
|
107
|
-
set("lasturl", value);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public String getLastEvent() {
|
|
111
|
-
return get("lastevent");
|
|
112
|
-
}
|
|
113
|
-
public void setLastEvent(String value) {
|
|
114
|
-
set("lastevent", value);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
public String getLastTarget() {
|
|
118
|
-
return get("lasttarget");
|
|
119
|
-
}
|
|
120
|
-
public void setLastTarget(String value) {
|
|
121
|
-
set("lasttarget", value);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
public Boolean getForceClient() {
|
|
125
|
-
return get("forceclient") == null
|
|
126
|
-
? null
|
|
127
|
-
: Boolean.parseBoolean(get("forceclient"));
|
|
128
|
-
}
|
|
129
|
-
public void setForceClient(Boolean value) {
|
|
130
|
-
set("forceclient", String.valueOf(value));
|
|
131
|
-
}
|
|
132
|
-
public Boolean getForceProxy() {
|
|
133
|
-
return get("forceproxy") == null
|
|
134
|
-
? null
|
|
135
|
-
: Boolean.parseBoolean(get("forceproxy"));
|
|
136
|
-
}
|
|
137
|
-
public void setForceProxy(Boolean value) {
|
|
138
|
-
set("forceproxy", String.valueOf(value));
|
|
139
|
-
}
|
|
140
|
-
public Boolean getForceBot() {
|
|
141
|
-
return get("forceproxy") == null
|
|
142
|
-
? null
|
|
143
|
-
: Boolean.parseBoolean(get("forcebot"));
|
|
144
|
-
}
|
|
145
|
-
public void setForceBot(Boolean value) {
|
|
146
|
-
set("forcebot", String.valueOf(value));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
private class GolfParams {
|
|
151
|
-
private String mEvent = null;
|
|
152
|
-
private String mTarget = null;
|
|
153
|
-
private Boolean mForce = false;
|
|
154
|
-
private Integer mSeq = -1;
|
|
155
|
-
private Boolean mJs = false;
|
|
156
|
-
private String mPath = null;
|
|
157
|
-
private Boolean mReload = false;
|
|
158
|
-
|
|
159
|
-
public GolfParams(HttpServletRequest req) {
|
|
160
|
-
mEvent = req.getParameter("event");
|
|
161
|
-
mTarget = req.getParameter("target");
|
|
162
|
-
mForce = req.getParameter("force") == null
|
|
163
|
-
? null
|
|
164
|
-
: Boolean.parseBoolean(req.getParameter("force"));
|
|
165
|
-
mSeq = req.getParameter("golf") == null
|
|
166
|
-
? null
|
|
167
|
-
: Integer.valueOf(req.getParameter("golf"));
|
|
168
|
-
mJs = req.getParameter("js") == null
|
|
169
|
-
? null
|
|
170
|
-
: Boolean.parseBoolean(req.getParameter("js"));
|
|
171
|
-
mPath = req.getParameter("path");
|
|
172
|
-
mReload = req.getParameter("reload") == null
|
|
173
|
-
? null
|
|
174
|
-
: Boolean.parseBoolean(req.getParameter("reload"));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
public String getEvent() { return mEvent; }
|
|
178
|
-
public String getTarget() { return mTarget; }
|
|
179
|
-
public Boolean getForce() { return mForce; }
|
|
180
|
-
public Integer getSeq() { return mSeq; }
|
|
181
|
-
public Boolean getJs() { return mJs; }
|
|
182
|
-
public String getPath() { return mPath; }
|
|
183
|
-
public Boolean getReload() { return mReload; }
|
|
184
|
-
|
|
185
|
-
public void setEvent(String v) { mEvent = v; }
|
|
186
|
-
public void setTarget(String v) { mTarget = v; }
|
|
187
|
-
public void setForce(Boolean v) { mForce = v; }
|
|
188
|
-
public void setSeq(Integer v) { mSeq = v; }
|
|
189
|
-
public void setJs(Boolean v) { mJs = v; }
|
|
190
|
-
public void setPath(String v) { mPath = v; }
|
|
191
|
-
public void setReload(Boolean v) { mReload = v; }
|
|
192
|
-
|
|
193
|
-
private String toQueryParam(String name, String p) {
|
|
194
|
-
return p != null ? name+"="+p : "";
|
|
195
|
-
}
|
|
196
|
-
private String toQueryParam(String name, Boolean p) {
|
|
197
|
-
return p != null ? name+"="+p.toString() : "";
|
|
198
|
-
}
|
|
199
|
-
private String toQueryParam(String name, Integer p) {
|
|
200
|
-
return p != null ? name+"="+p.toString() : "";
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Contains state info for a golf request. This is what should be passed
|
|
206
|
-
* around rather than the raw request or response.
|
|
207
|
-
*/
|
|
208
|
-
public class GolfContext {
|
|
209
|
-
|
|
210
|
-
public HttpServletRequest request = null;
|
|
211
|
-
public HttpServletResponse response = null;
|
|
212
|
-
public GolfParams p = null;
|
|
213
|
-
public GolfSession s = null;
|
|
214
|
-
public String servletUrl = null;
|
|
215
|
-
public String urlHash = null;
|
|
216
|
-
public BrowserVersion browser = BrowserVersion.FIREFOX_2;
|
|
217
|
-
public StoredJSVM jsvm = null;
|
|
218
|
-
public Boolean logging = true;
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Constructor.
|
|
222
|
-
*
|
|
223
|
-
* FIXME implement this as a singleton
|
|
224
|
-
*
|
|
225
|
-
* @param request the http request object
|
|
226
|
-
* @param response the http response object
|
|
227
|
-
*/
|
|
228
|
-
public GolfContext(HttpServletRequest request,
|
|
229
|
-
HttpServletResponse response) {
|
|
230
|
-
this.request = request;
|
|
231
|
-
this.response = response;
|
|
232
|
-
this.p = new GolfParams(request);
|
|
233
|
-
this.s = new GolfSession(request);
|
|
234
|
-
this.servletUrl =
|
|
235
|
-
request
|
|
236
|
-
.getRequestURL()
|
|
237
|
-
.toString()
|
|
238
|
-
.replaceFirst(";jsessionid=.*$", "")
|
|
239
|
-
.replaceFirst(
|
|
240
|
-
"^(https?://[^/]+"+Pattern.quote(request.getContextPath())+").*$",
|
|
241
|
-
"$1"
|
|
242
|
-
);
|
|
243
|
-
this.urlHash =
|
|
244
|
-
request
|
|
245
|
-
.getRequestURL()
|
|
246
|
-
.toString()
|
|
247
|
-
.replaceFirst(";jsessionid=.*$", "")
|
|
248
|
-
.replaceFirst(
|
|
249
|
-
"^https?://[^/]+"+Pattern.quote(request.getContextPath()),
|
|
250
|
-
""
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
public void init() throws ServletException, RedirectException {
|
|
255
|
-
// some servlet containers have been known to produce a null urlHash
|
|
256
|
-
urlHash = (urlHash == null ? "" : urlHash);
|
|
257
|
-
|
|
258
|
-
// reload the page in proxy mode => destroy old jsvm
|
|
259
|
-
if (p.getReload() != null && p.getReload().booleanValue()) {
|
|
260
|
-
log(this, LOG_INFO, "RELOAD via query parameter");
|
|
261
|
-
mJsvms.remove(request.getSession().getId());
|
|
262
|
-
request.getSession(true).invalidate();
|
|
263
|
-
this.s = new GolfSession(request);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// ensure that the URL is in the standard form
|
|
267
|
-
|
|
268
|
-
// http://example.com/app//some/path/ ==>>
|
|
269
|
-
// servletUrl => http://example.com/app
|
|
270
|
-
// urlHash => //some/path/
|
|
271
|
-
|
|
272
|
-
if (urlHash.startsWith("/")) {
|
|
273
|
-
servletUrl = servletUrl + "/";
|
|
274
|
-
urlHash = urlHash.replaceFirst("^/", "");
|
|
275
|
-
} else {
|
|
276
|
-
//System.err.println("{{{ REDIRECT 0 }}}");
|
|
277
|
-
throw new PermanentRedirectException(
|
|
278
|
-
response.encodeRedirectURL(servletUrl+"/"+urlHash));
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// fetch the jsvm for this guy
|
|
282
|
-
jsvm = mJsvms.get(request.getSession().getId());
|
|
283
|
-
|
|
284
|
-
if (jsvm == null)
|
|
285
|
-
jsvm = new StoredJSVM((WebClient) null);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
public boolean hasEvent() {
|
|
289
|
-
return (this.p.getEvent() != null && this.p.getTarget() != null);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
private static ConcurrentHashMap<String, StoredJSVM> mJsvms =
|
|
294
|
-
new ConcurrentHashMap<String, StoredJSVM>();
|
|
295
|
-
|
|
296
|
-
private static int mLogLevel = LOG_ALL;
|
|
297
|
-
private static String mNewHtml = null;
|
|
298
|
-
private static String mNewHtmlFc = null;
|
|
299
|
-
private static String mErrorPage = null;
|
|
300
|
-
private static String mJsDetect = null;
|
|
301
|
-
private static String mDevMode = null;
|
|
302
|
-
private static String mPoolSize = null;
|
|
303
|
-
private static String mPoolExpire = null;
|
|
304
|
-
private static String mAppVersion = null;
|
|
305
|
-
private static AtomicBoolean mBotMutex = new AtomicBoolean();
|
|
306
|
-
private static ArrayList<String> mForceProxy = new ArrayList<String>();
|
|
307
|
-
private static ArrayList<String> mForceClient = new ArrayList<String>();
|
|
308
|
-
private static ArrayList<String> mForceBot = new ArrayList<String>();
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
|
|
312
|
-
*/
|
|
313
|
-
public void init(ServletConfig config) throws ServletException {
|
|
314
|
-
super.init(config); // tricky little guy
|
|
315
|
-
|
|
316
|
-
// init parameters
|
|
317
|
-
mDevMode = config.getInitParameter("devmode");
|
|
318
|
-
mPoolSize = config.getInitParameter("poolsize");
|
|
319
|
-
mPoolExpire = config.getInitParameter("poolexpire");
|
|
320
|
-
mAppVersion = config.getInitParameter("version");
|
|
321
|
-
|
|
322
|
-
// default values
|
|
323
|
-
mDevMode = (mDevMode != null ? mDevMode : "true" );
|
|
324
|
-
mPoolSize = (mPoolSize != null ? mPoolSize : "10" );
|
|
325
|
-
mPoolExpire = (mPoolExpire != null ? mPoolExpire : "900" ); // 15 min
|
|
326
|
-
|
|
327
|
-
// set initial values
|
|
328
|
-
mBotMutex.set(false);
|
|
329
|
-
|
|
330
|
-
// process the static files that need to be kept in memory
|
|
331
|
-
cacheStaticFiles();
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Serve http requests!
|
|
336
|
-
*
|
|
337
|
-
* @param request the http request object
|
|
338
|
-
* @param response the http response object
|
|
339
|
-
*/
|
|
340
|
-
public void service(HttpServletRequest request, HttpServletResponse response)
|
|
341
|
-
throws IOException, ServletException {
|
|
342
|
-
GolfContext context = null;
|
|
343
|
-
String result = null;
|
|
344
|
-
|
|
345
|
-
// All query string parameters are considered to be arguments directed
|
|
346
|
-
// to the golf container. The app itself gets its arguments in the path
|
|
347
|
-
// info.
|
|
348
|
-
|
|
349
|
-
try {
|
|
350
|
-
// create the context object for this request
|
|
351
|
-
context = new GolfContext(request, response);
|
|
352
|
-
|
|
353
|
-
// log the incoming request before any manipulation is done
|
|
354
|
-
logRequest(context);
|
|
355
|
-
|
|
356
|
-
// initialize context
|
|
357
|
-
context.init();
|
|
358
|
-
|
|
359
|
-
/*
|
|
360
|
-
String url = context.request.getRequestURL().toString()
|
|
361
|
-
.replaceFirst(";jsessionid=.*$", "");
|
|
362
|
-
|
|
363
|
-
if (! url.endsWith("/")) {
|
|
364
|
-
//System.err.println("{{{ REDIRECT 7 }}}");
|
|
365
|
-
throw new PermanentRedirectException(
|
|
366
|
-
context.response.encodeRedirectURL(url + "/"));
|
|
367
|
-
}
|
|
368
|
-
*/
|
|
369
|
-
|
|
370
|
-
// handle your business
|
|
371
|
-
if (context.p.getPath() != null)
|
|
372
|
-
doStaticResourceGet(context);
|
|
373
|
-
else
|
|
374
|
-
doDynamicResourceGet(context);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
catch (PermanentRedirectException r) {
|
|
378
|
-
// 301 PERMANENTLY MOVED
|
|
379
|
-
logResponse(context, 301);
|
|
380
|
-
log(context, LOG_INFO, "301 ---to--> "+r.getMessage());
|
|
381
|
-
context.response.setHeader("Location", r.getMessage());
|
|
382
|
-
context.response.sendError(301);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
catch (RedirectException r) {
|
|
386
|
-
// 302 FOUND
|
|
387
|
-
logResponse(context, 302);
|
|
388
|
-
log(context, LOG_INFO, "302 ---to--> "+r.getMessage());
|
|
389
|
-
context.response.sendRedirect(r.getMessage());
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
catch (FileNotFoundException e) {
|
|
393
|
-
// 404 NOT FOUND
|
|
394
|
-
logResponse(context, 404);
|
|
395
|
-
errorPage(context, HttpServletResponse.SC_NOT_FOUND, e);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
catch (Exception x) {
|
|
399
|
-
// 500 INTERNAL SERVER ERROR
|
|
400
|
-
logResponse(context, 500);
|
|
401
|
-
x.printStackTrace();
|
|
402
|
-
errorPage(context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, x);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* (Re)build static files and cache them in memory
|
|
408
|
-
*/
|
|
409
|
-
public void cacheStaticFiles() throws ServletException {
|
|
410
|
-
try {
|
|
411
|
-
if (Boolean.parseBoolean(mDevMode)) {
|
|
412
|
-
Main.cacheComponentsFile();
|
|
413
|
-
Main.cacheNewDotHtmlFile();
|
|
414
|
-
}
|
|
415
|
-
mNewHtml =
|
|
416
|
-
(new GolfResource(getServletContext(), Main.NEW_HTML)).toString();
|
|
417
|
-
mNewHtmlFc =
|
|
418
|
-
(new GolfResource(getServletContext(), Main.NEW_FC_HTML)).toString();
|
|
419
|
-
mErrorPage =
|
|
420
|
-
(new GolfResource(getServletContext(), Main.ERROR_HTML)).toString();
|
|
421
|
-
mJsDetect =
|
|
422
|
-
(new GolfResource(getServletContext(), Main.JSDETECT_HTML)).toString();
|
|
423
|
-
|
|
424
|
-
try {
|
|
425
|
-
// wait for resource to be available
|
|
426
|
-
while (!mBotMutex.compareAndSet(false, true));
|
|
427
|
-
|
|
428
|
-
mForceProxy =
|
|
429
|
-
(new GolfResource(getServletContext(), Main.FORCEPROXY_TXT))
|
|
430
|
-
.toArrayList();
|
|
431
|
-
|
|
432
|
-
mForceClient =
|
|
433
|
-
(new GolfResource(getServletContext(), Main.FORCECLIENT_TXT))
|
|
434
|
-
.toArrayList();
|
|
435
|
-
|
|
436
|
-
mForceBot =
|
|
437
|
-
(new GolfResource(getServletContext(), Main.FORCEBOT_TXT))
|
|
438
|
-
.toArrayList();
|
|
439
|
-
|
|
440
|
-
} catch (FileNotFoundException fx) {
|
|
441
|
-
} finally {
|
|
442
|
-
mBotMutex.set(false);
|
|
443
|
-
}
|
|
444
|
-
} catch (Exception e) {
|
|
445
|
-
throw new ServletException("can't cache static files", e);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Do text processing of html to inject server/client specific things, etc.
|
|
451
|
-
*
|
|
452
|
-
* @param page the html page contents
|
|
453
|
-
* @param context the golf request object
|
|
454
|
-
* @param server whether to process for serverside or clientside
|
|
455
|
-
* @return the processed page html contents
|
|
456
|
-
*/
|
|
457
|
-
private static String preprocess(String page, GolfContext context, boolean server) {
|
|
458
|
-
String sid = context.request.getSession().getId();
|
|
459
|
-
|
|
460
|
-
// pattern matching all script tags (should this be removed?)
|
|
461
|
-
String pat1 = "<noscript>.*</noscript>";
|
|
462
|
-
|
|
463
|
-
// pattern matching all script tags (should this be removed?)
|
|
464
|
-
String pat2 =
|
|
465
|
-
"<script type=\"text/javascript\"[^>]*>([^<]|//<!\\[CDATA\\[)*</script>";
|
|
466
|
-
|
|
467
|
-
// document type: xhtml
|
|
468
|
-
String dtd =
|
|
469
|
-
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" +
|
|
470
|
-
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
|
|
471
|
-
|
|
472
|
-
// remove xml tag (why is it even there?)
|
|
473
|
-
if (!server)
|
|
474
|
-
page = page.replaceFirst("^<\\?xml [^>]+>\n", "");
|
|
475
|
-
|
|
476
|
-
// robots must not index event proxy (because infinite loops, etc.)
|
|
477
|
-
if (!context.hasEvent())
|
|
478
|
-
page = page.replaceFirst("noindex,nofollow", "index,follow");
|
|
479
|
-
|
|
480
|
-
// remove the golfid attribute as it's not necessary on the client
|
|
481
|
-
// and it is frowned upon by the w3c validator
|
|
482
|
-
if (!server)
|
|
483
|
-
page = page.replaceAll("(<[^>]+) golfid=\"[0-9]+\"", "$1");
|
|
484
|
-
|
|
485
|
-
if (! context.s.getJs().booleanValue() && !server) {
|
|
486
|
-
// proxy mode: remove javascript/noscript except for serverside
|
|
487
|
-
page = page.replaceAll(pat1, "");
|
|
488
|
-
page = page.replaceAll(pat2, "");
|
|
489
|
-
|
|
490
|
-
for (int i=0, j=0; (i=page.indexOf("<style", i)) != -1; i=j) {
|
|
491
|
-
j = page.indexOf("</style>", i);
|
|
492
|
-
page = page.substring(0, i)
|
|
493
|
-
+ page.substring(i, j).replaceAll(">", ">")
|
|
494
|
-
.replaceAll("<", "<")
|
|
495
|
-
.replaceAll("&", "&")
|
|
496
|
-
.replaceAll("'", "'")
|
|
497
|
-
.replaceAll("\n", "") // FIXME this is sketchy
|
|
498
|
-
+ page.substring(j);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (context.s.getForceBot().booleanValue()) {
|
|
502
|
-
page = page.replaceAll("(<[^>]+) style=\"[^\"]*\"", "$1");
|
|
503
|
-
page = page.replaceAll("(<[^>]+) style='[^']*'", "$1");
|
|
504
|
-
page = page.replaceAll("(<[^>]+) class=\"[^\"]*\"", "$1");
|
|
505
|
-
page = page.replaceAll("(<[^>]+) class='[^']*'", "$1");
|
|
506
|
-
}
|
|
507
|
-
} else {
|
|
508
|
-
// on the client window.serverside must be false, and vice versa
|
|
509
|
-
page = page.replaceFirst("__SVRSIDE__", (server ? "true" : "false"));
|
|
510
|
-
|
|
511
|
-
// import the session ID into the javascript environment
|
|
512
|
-
page = page.replaceFirst("__SESSID__", sid);
|
|
513
|
-
|
|
514
|
-
// the servlet url (shenanigans here)
|
|
515
|
-
page = page.replaceFirst("__SERVLET_URL__", context.servletUrl);
|
|
516
|
-
|
|
517
|
-
// the url fragment (shenanigans here)
|
|
518
|
-
page = page.replaceFirst("__URL_HASH__", context.urlHash);
|
|
519
|
-
|
|
520
|
-
// bot mode forced?
|
|
521
|
-
page = page.replaceFirst("__FORCEBOT__",
|
|
522
|
-
context.s.getForceBot().toString());
|
|
523
|
-
|
|
524
|
-
// proxy mode forced?
|
|
525
|
-
page = page.replaceFirst("__FORCEPROXY__",
|
|
526
|
-
context.s.getForceProxy().toString());
|
|
527
|
-
|
|
528
|
-
// client mode forced?
|
|
529
|
-
page = page.replaceFirst("__FORCECLIENT__",
|
|
530
|
-
context.s.getForceClient().toString());
|
|
531
|
-
|
|
532
|
-
// the golf version
|
|
533
|
-
page = page.replaceFirst("__GOLF_VERSION__", mAppVersion);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// no dtd for serverside because it breaks the xml parser
|
|
537
|
-
return (server ? "" : dtd) + page;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Show error page.
|
|
542
|
-
*
|
|
543
|
-
* @param context the golf request context
|
|
544
|
-
* @param e the exception
|
|
545
|
-
*/
|
|
546
|
-
public void errorPage(GolfContext context, int status, Exception e) {
|
|
547
|
-
try {
|
|
548
|
-
PrintWriter out = context.response.getWriter();
|
|
549
|
-
|
|
550
|
-
String errHtml =
|
|
551
|
-
mErrorPage.replaceAll("<%error%>", HTMLEntityEncode(e.getMessage()));
|
|
552
|
-
|
|
553
|
-
context.response.setStatus(status);
|
|
554
|
-
context.response.setContentType("text/html");
|
|
555
|
-
|
|
556
|
-
out.print(errHtml);
|
|
557
|
-
} catch (Exception x) {
|
|
558
|
-
x.printStackTrace();
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
* Send a proxied response.
|
|
564
|
-
*
|
|
565
|
-
* @param context the golf context for this request
|
|
566
|
-
*/
|
|
567
|
-
private void doProxy(GolfContext context) throws FileNotFoundException,
|
|
568
|
-
IOException, URISyntaxException, RedirectException, ServletException {
|
|
569
|
-
String sid = context.request.getSession().getId();
|
|
570
|
-
HtmlPage result = context.jsvm.lastPage;
|
|
571
|
-
|
|
572
|
-
String path = context.urlHash;
|
|
573
|
-
String event = context.p.getEvent();
|
|
574
|
-
String target = context.p.getTarget();
|
|
575
|
-
WebClient client = context.jsvm.client;
|
|
576
|
-
|
|
577
|
-
String lastEvent = context.s.getLastEvent();
|
|
578
|
-
String lastTarget = context.s.getLastTarget();
|
|
579
|
-
String lastUrl = context.s.getLastUrl();
|
|
580
|
-
|
|
581
|
-
context.jsvm.lastPage = null;
|
|
582
|
-
context.s.setLastEvent(null);
|
|
583
|
-
context.s.setLastTarget(null);
|
|
584
|
-
context.s.setLastUrl(null);
|
|
585
|
-
|
|
586
|
-
if (result == null || !path.equals(lastUrl)) {
|
|
587
|
-
if (lastEvent == null || lastTarget == null || !path.equals(lastUrl)) {
|
|
588
|
-
if (event != null && target != null && client != null) {
|
|
589
|
-
|
|
590
|
-
// update last access time
|
|
591
|
-
context.jsvm.lastAccessTime = (new Date()).getTime();
|
|
592
|
-
|
|
593
|
-
if (event.equals("onclick")) {
|
|
594
|
-
// nothing here
|
|
595
|
-
} else if (event.equals("onsubmit")) {
|
|
596
|
-
Map<String, String[]> pmap = context.request.getParameterMap();
|
|
597
|
-
for (String key : pmap.keySet()) {
|
|
598
|
-
String val = pmap.get(key)[0].replaceAll("[\"]", "\\x22");
|
|
599
|
-
|
|
600
|
-
String script = "jQuery(\"[name='"+key+"']\").val(\""+val+"\");";
|
|
601
|
-
|
|
602
|
-
result = (HtmlPage) client.getCurrentWindow().getEnclosedPage();
|
|
603
|
-
result.executeJavaScript(script);
|
|
604
|
-
}
|
|
605
|
-
} else {
|
|
606
|
-
throw new ServletException("unsupported event for proxy: "+event);
|
|
607
|
-
}
|
|
608
|
-
context.s.setLastEvent(event);
|
|
609
|
-
context.s.setLastTarget(target);
|
|
610
|
-
context.s.setLastUrl(path);
|
|
611
|
-
if (context.request.getQueryString() != null) {
|
|
612
|
-
//System.err.println("{{{ REDIRECT 1 }}}");
|
|
613
|
-
throw new RedirectException(proxyURLEncode(
|
|
614
|
-
context.response.encodeRedirectURL(context.servletUrl + path)));
|
|
615
|
-
} else {
|
|
616
|
-
lastEvent = context.s.getLastEvent();
|
|
617
|
-
lastTarget = context.s.getLastTarget();
|
|
618
|
-
lastUrl = context.s.getLastUrl();
|
|
619
|
-
}
|
|
620
|
-
} else if (client == null) {
|
|
621
|
-
log(context, LOG_INFO, "*** INITIALIZING NEW CLIENT ***");
|
|
622
|
-
log(context, LOG_INFO, "Running JSVMs, before GC: " + mJsvms.size());
|
|
623
|
-
|
|
624
|
-
createNewJsvm(context);
|
|
625
|
-
|
|
626
|
-
log(context, LOG_INFO, "Running JSVMs, after GC: " + mJsvms.size());
|
|
627
|
-
|
|
628
|
-
client = context.jsvm.client;
|
|
629
|
-
|
|
630
|
-
// write any alert() calls to the log
|
|
631
|
-
client.setAlertHandler(new AlertHandler() {
|
|
632
|
-
public void handleAlert(Page page, String message) {
|
|
633
|
-
System.err.println("ALERT: " + message);
|
|
634
|
-
}
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
// if this isn't long enough it'll timeout before all ajax is complete
|
|
638
|
-
client.setJavaScriptTimeout(JSVM_TIMEOUT);
|
|
639
|
-
|
|
640
|
-
// the blank skeleton html template
|
|
641
|
-
String newHtml = mNewHtml;
|
|
642
|
-
|
|
643
|
-
// do not pass query string to the app, as those parameters are meant
|
|
644
|
-
// only for the golf container itself.
|
|
645
|
-
|
|
646
|
-
StringWebResponse response = new StringWebResponse(
|
|
647
|
-
preprocess(newHtml, context, true),
|
|
648
|
-
new URL(context.servletUrl + "#" + context.urlHash)
|
|
649
|
-
);
|
|
650
|
-
|
|
651
|
-
// run it through htmlunit
|
|
652
|
-
result = (HtmlPage) context.jsvm.client.loadWebResponseInto(
|
|
653
|
-
response,
|
|
654
|
-
client.getCurrentWindow()
|
|
655
|
-
);
|
|
656
|
-
} else {
|
|
657
|
-
String script = "jQuery.address.value('"+context.urlHash+"');";
|
|
658
|
-
result = (HtmlPage) client.getCurrentWindow().getEnclosedPage();
|
|
659
|
-
result.executeJavaScript(script);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
if (lastEvent != null && lastTarget != null && path.equals(lastUrl)) {
|
|
664
|
-
if (client != null) {
|
|
665
|
-
String script;
|
|
666
|
-
if (lastEvent.equals("onclick")) {
|
|
667
|
-
script = "jQuery(\"[golfid='"+lastTarget+"']\").click()";
|
|
668
|
-
} else if (lastEvent.equals("onsubmit")) {
|
|
669
|
-
script = "jQuery(\"[golfid='"+lastTarget+"']\").submit()";
|
|
670
|
-
} else {
|
|
671
|
-
//System.err.println("{{{ REDIRECT 2 }}}");
|
|
672
|
-
throw new RedirectException(proxyURLEncode(
|
|
673
|
-
context.response.encodeRedirectURL(context.servletUrl + path)));
|
|
674
|
-
}
|
|
675
|
-
result = (HtmlPage) client.getCurrentWindow().getEnclosedPage();
|
|
676
|
-
result.executeJavaScript(script);
|
|
677
|
-
} else {
|
|
678
|
-
//System.err.println("{{{ REDIRECT 3 }}}");
|
|
679
|
-
throw new RedirectException(proxyURLEncode(
|
|
680
|
-
context.response.encodeRedirectURL(context.servletUrl + path)));
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
String loc = (String) result.executeJavaScript(
|
|
685
|
-
"window.location.href").getJavaScriptResult();
|
|
686
|
-
|
|
687
|
-
if (!loc.startsWith(context.servletUrl)) {
|
|
688
|
-
//System.err.println("{{{ REDIRECT 4 }}}");
|
|
689
|
-
throw new RedirectException(
|
|
690
|
-
proxyURLEncode(context.response.encodeRedirectURL(loc)));
|
|
691
|
-
} else {
|
|
692
|
-
loc = loc.replaceFirst("^[^#]+#", "");
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
if (!loc.equals(path) || context.request.getQueryString() != null) {
|
|
696
|
-
context.jsvm.lastPage = result;
|
|
697
|
-
context.s.setLastUrl(loc);
|
|
698
|
-
//System.err.println("{{{ REDIRECT 5 }}}");
|
|
699
|
-
throw new RedirectException(proxyURLEncode(
|
|
700
|
-
context.response.encodeRedirectURL(context.servletUrl + loc)));
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
Iterator<HtmlAnchor> anchors = result.getAnchors().iterator();
|
|
705
|
-
while (anchors.hasNext()) {
|
|
706
|
-
HtmlAnchor a = anchors.next();
|
|
707
|
-
a.setAttribute("href",context.response.encodeURL(a.getHrefAttribute()));
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
result.executeJavaScript(
|
|
711
|
-
"jQuery('.component').each( " +
|
|
712
|
-
"function() { "+
|
|
713
|
-
"var elem = jQuery(this).children().eq(0); "+
|
|
714
|
-
"if (elem) { "+
|
|
715
|
-
"jQuery.golf.jss(elem, true); "+
|
|
716
|
-
"} "+
|
|
717
|
-
"} "+
|
|
718
|
-
")"
|
|
719
|
-
);
|
|
720
|
-
|
|
721
|
-
String html = preprocess(result.asXml(), context, false);
|
|
722
|
-
sendResponse(context, html, "text/html", false);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* Send a non-proxied response.
|
|
727
|
-
*
|
|
728
|
-
* @param context the golf context for this request
|
|
729
|
-
*/
|
|
730
|
-
private void doNoProxy(GolfContext context) throws Exception {
|
|
731
|
-
// the blank skeleton html template
|
|
732
|
-
String html = (context.s.getForceClient() ? mNewHtmlFc : mNewHtml);
|
|
733
|
-
sendResponse(context, preprocess(html, context, false), "text/html", true);
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* First clean out any old JSVMs that might be hanging around, then
|
|
738
|
-
* make sure there is room for another jsvm.
|
|
739
|
-
*/
|
|
740
|
-
private void createNewJsvm(GolfContext context) throws ServletException {
|
|
741
|
-
int psize = Integer.parseInt(mPoolSize);
|
|
742
|
-
long ptime = Long.parseLong(mPoolExpire) * 1000L; // convert sec --> msec
|
|
743
|
-
long ctime = (new Date()).getTime();
|
|
744
|
-
|
|
745
|
-
for (String key : mJsvms.keySet())
|
|
746
|
-
if (ctime - mJsvms.get(key).lastAccessTime > ptime)
|
|
747
|
-
mJsvms.remove(key);
|
|
748
|
-
|
|
749
|
-
if (mJsvms.size() >= psize) {
|
|
750
|
-
throw new ServletException(
|
|
751
|
-
"The server has too many concurrent proxy sessions right now. "+
|
|
752
|
-
"Please enable javascript in your browser (if you can) or try "+
|
|
753
|
-
"again later."
|
|
754
|
-
);
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
context.jsvm.client = new WebClient(context.browser);
|
|
758
|
-
mJsvms.put(context.request.getSession().getId(), context.jsvm);
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
/**
|
|
762
|
-
* Do the dynamic request.
|
|
763
|
-
*
|
|
764
|
-
* @param context the golf context for this request
|
|
765
|
-
*/
|
|
766
|
-
private void doDynamicResourceGet(GolfContext context) throws Exception {
|
|
767
|
-
|
|
768
|
-
HttpSession session = context.request.getSession();
|
|
769
|
-
String remoteAddr = context.request.getRemoteAddr();
|
|
770
|
-
String sessionAddr = context.s.getIpAddr();
|
|
771
|
-
Boolean forcebot = context.s.getForceBot();
|
|
772
|
-
Boolean forceproxy = context.s.getForceProxy();
|
|
773
|
-
Boolean forceclient = context.s.getForceClient();
|
|
774
|
-
Boolean forceParam = context.p.getForce();
|
|
775
|
-
Boolean jsParam = context.p.getJs();
|
|
776
|
-
String sid = session.getId();
|
|
777
|
-
String uagent = context.request.getHeader("User-Agent");
|
|
778
|
-
|
|
779
|
-
if (sid == null)
|
|
780
|
-
throw new Exception("sid is null");
|
|
781
|
-
|
|
782
|
-
if (Boolean.parseBoolean(mDevMode)) {
|
|
783
|
-
cacheStaticFiles();
|
|
784
|
-
context.s.setForceProxy(forceproxy = null);
|
|
785
|
-
context.s.setForceClient(forceclient = null);
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
// forcebot: Match regex to user agent string.
|
|
789
|
-
// If match, treat user agent as a bot (no css,
|
|
790
|
-
// no presentation cruft, cleaner markup).
|
|
791
|
-
|
|
792
|
-
// FIXME: store this info in session unless in devmode, maybe
|
|
793
|
-
if (forcebot == null) {
|
|
794
|
-
forcebot = multipatternMatch(uagent, mForceBot);
|
|
795
|
-
context.s.setForceBot(forcebot);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
// forceproxy: Match regex to user agent string.
|
|
799
|
-
// If match, force proxy mode immediately. Forcebot
|
|
800
|
-
// implies forceproxy.
|
|
801
|
-
|
|
802
|
-
// FIXME: store this info in session unless in devmode, maybe
|
|
803
|
-
if (forceproxy == null) {
|
|
804
|
-
if (forceproxy =
|
|
805
|
-
(multipatternMatch(uagent, mForceProxy) || forcebot)) {
|
|
806
|
-
context.s.setJs(false);
|
|
807
|
-
context.s.setSeq(1);
|
|
808
|
-
}
|
|
809
|
-
context.s.setForceProxy(forceproxy);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
// forceclient: Match regex to user agent string.
|
|
813
|
-
// If match, force client mode immediately, unless
|
|
814
|
-
// forceproxy is set (forceproxy has higher precedence).
|
|
815
|
-
|
|
816
|
-
// FIXME: store this info in session unless in devmode, maybe
|
|
817
|
-
if (forceclient == null) {
|
|
818
|
-
forceclient = false;
|
|
819
|
-
if (forceproxy == false) {
|
|
820
|
-
if (forceclient = multipatternMatch(uagent, mForceClient)) {
|
|
821
|
-
context.s.setJs(true);
|
|
822
|
-
context.s.setSeq(1);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
context.s.setForceClient(forceclient);
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
Boolean forceUa = forceproxy || forceclient;
|
|
829
|
-
|
|
830
|
-
if (! session.isNew() || forceUa) {
|
|
831
|
-
if (!forceUa && forceParam != null && forceParam.booleanValue())
|
|
832
|
-
context.s.setSeq(0);
|
|
833
|
-
|
|
834
|
-
int seq = (context.s.getSeq() == null ? 0 : (int) context.s.getSeq());
|
|
835
|
-
|
|
836
|
-
context.s.setSeq(++seq);
|
|
837
|
-
|
|
838
|
-
if (forceUa || sessionAddr != null && sessionAddr.equals(remoteAddr)) {
|
|
839
|
-
if (!forceUa && seq == 1) {
|
|
840
|
-
if (jsParam != null) {
|
|
841
|
-
String uri;
|
|
842
|
-
boolean js = jsParam.booleanValue();
|
|
843
|
-
|
|
844
|
-
context.s.setJs(js);
|
|
845
|
-
|
|
846
|
-
if (js) {
|
|
847
|
-
uri = context.servletUrl +
|
|
848
|
-
(context.urlHash.length() > 0 ? "#" + context.urlHash : "");
|
|
849
|
-
} else {
|
|
850
|
-
uri = context.request.getRequestURL().toString();
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
//System.err.println("{{{ REDIRECT 6 }}}");
|
|
854
|
-
throw new RedirectException(
|
|
855
|
-
context.response.encodeRedirectURL(uri));
|
|
856
|
-
}
|
|
857
|
-
} else if (forceUa || seq >= 2) {
|
|
858
|
-
if (forceUa || context.s.getJs() != null) {
|
|
859
|
-
// FIXME: lurking NPE if you change this
|
|
860
|
-
if (forceclient ||
|
|
861
|
-
(!forceproxy && context.s.getJs().booleanValue()))
|
|
862
|
-
doNoProxy(context);
|
|
863
|
-
else
|
|
864
|
-
doProxy(context);
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
session.invalidate();
|
|
871
|
-
context.s = new GolfSession(context.request);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
context.s.setSeq(new Integer(0));
|
|
875
|
-
context.s.setIpAddr(remoteAddr);
|
|
876
|
-
|
|
877
|
-
String jsDetect = mJsDetect;
|
|
878
|
-
|
|
879
|
-
jsDetect =
|
|
880
|
-
jsDetect.replaceAll("__HAVE_JS__", ";jsessionid="+sid+"?js=true");
|
|
881
|
-
jsDetect =
|
|
882
|
-
jsDetect.replaceAll("__DONT_HAVE_JS__", ";jsessionid="+sid+"?js=false");
|
|
883
|
-
|
|
884
|
-
sendResponse(context, jsDetect, "text/html", false);
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
private boolean multipatternMatch(String ua, ArrayList<String> pats) {
|
|
888
|
-
for (String i : pats)
|
|
889
|
-
if (ua.matches(i))
|
|
890
|
-
return true;
|
|
891
|
-
return false;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
private void sendResponse(GolfContext context, String html,
|
|
895
|
-
String contentType, boolean canCache) throws IOException {
|
|
896
|
-
context.response.setContentType(contentType);
|
|
897
|
-
|
|
898
|
-
if (canCache)
|
|
899
|
-
setCachable(context);
|
|
900
|
-
|
|
901
|
-
PrintWriter out = context.response.getWriter();
|
|
902
|
-
out.print(html);
|
|
903
|
-
out.close();
|
|
904
|
-
logResponse(context, 200);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
private void setCachable(GolfContext context) {
|
|
908
|
-
long currentTime = System.currentTimeMillis();
|
|
909
|
-
long later = 24*60*60*1000; // a day (milliseconds)
|
|
910
|
-
context.response.setDateHeader("Expires", currentTime + later);
|
|
911
|
-
context.response.setHeader("Cache-Control", "max-age=3600,public");
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
/**
|
|
915
|
-
* Handle a request for a static resource.
|
|
916
|
-
*
|
|
917
|
-
* @param context the golf context for this request
|
|
918
|
-
*/
|
|
919
|
-
private void doStaticResourceGet(GolfContext context)
|
|
920
|
-
throws FileNotFoundException, IOException, JSONException {
|
|
921
|
-
String path = context.p.getPath();
|
|
922
|
-
|
|
923
|
-
if (path.matches("^[/]*\\."))
|
|
924
|
-
throw new FileNotFoundException();
|
|
925
|
-
|
|
926
|
-
if (! path.startsWith("/"))
|
|
927
|
-
path = "/" + path;
|
|
928
|
-
|
|
929
|
-
GolfResource res = new GolfResource(getServletContext(), path);
|
|
930
|
-
|
|
931
|
-
context.response.setContentType(res.getMimeType());
|
|
932
|
-
setCachable(context);
|
|
933
|
-
|
|
934
|
-
if (res.getMimeType().startsWith("text/")) {
|
|
935
|
-
PrintWriter out = context.response.getWriter();
|
|
936
|
-
out.print(res.toString());
|
|
937
|
-
} else {
|
|
938
|
-
OutputStream out = context.response.getOutputStream();
|
|
939
|
-
out.write(res.toByteArray());
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
logResponse(context, 200);
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* Format a nice log message.
|
|
947
|
-
*
|
|
948
|
-
* @param context the golf context for this request
|
|
949
|
-
* @param s the log message
|
|
950
|
-
* @return the formatted log message
|
|
951
|
-
*/
|
|
952
|
-
private String fmt(GolfContext context, String s) {
|
|
953
|
-
String sid = null;
|
|
954
|
-
String ip = null;
|
|
955
|
-
|
|
956
|
-
if (context != null) {
|
|
957
|
-
sid = context.request.getSession().getId();
|
|
958
|
-
ip = context.request.getRemoteHost();
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
sid = sid != null ? "[" + sid.toUpperCase().replaceAll(
|
|
962
|
-
"(...)(?=...)", "$1.") + "] " : "";
|
|
963
|
-
ip = ip != null ? ip+"\n >>> " : "";
|
|
964
|
-
|
|
965
|
-
return sid + ip + s;
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
/**
|
|
969
|
-
* Send a formatted message to the logs.
|
|
970
|
-
*
|
|
971
|
-
* @param context the golf context for this request
|
|
972
|
-
* @param level the severity of the message (LOG_TRACE to LOG_FATAL)
|
|
973
|
-
* @param s the log message
|
|
974
|
-
*/
|
|
975
|
-
public void log(GolfContext context, int level, String s) {
|
|
976
|
-
ServletContext c = getServletContext();
|
|
977
|
-
if (context.logging && mLogLevel <= level)
|
|
978
|
-
c.log(fmt(context, s));
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
/**
|
|
982
|
-
* Logs a http servlet request.
|
|
983
|
-
*
|
|
984
|
-
* @param context the golf context for this request
|
|
985
|
-
*/
|
|
986
|
-
private void logRequest(GolfContext context) {
|
|
987
|
-
String method = context.request.getMethod();
|
|
988
|
-
String path = context.urlHash;
|
|
989
|
-
String query = context.request.getQueryString();
|
|
990
|
-
String host = context.request.getRemoteHost();
|
|
991
|
-
String sid = context.request.getSession().getId();
|
|
992
|
-
String uagent = context.request.getHeader("User-Agent");
|
|
993
|
-
|
|
994
|
-
String line = method + " " + path + (query != null ? "?" + query : "");
|
|
995
|
-
|
|
996
|
-
log(context, LOG_INFO, line);
|
|
997
|
-
log(context, LOG_INFO, uagent);
|
|
998
|
-
|
|
999
|
-
//System.out.println("||||||||||||||||||||||||||||||||||||||");
|
|
1000
|
-
//Enumeration headerNames = context.request.getHeaderNames();
|
|
1001
|
-
//while(headerNames.hasMoreElements()) {
|
|
1002
|
-
// String headerName = (String)headerNames.nextElement();
|
|
1003
|
-
// System.out.println("||||||||||| " + headerName + ": "
|
|
1004
|
-
// + context.request.getHeader(headerName));
|
|
1005
|
-
//}
|
|
1006
|
-
//System.out.println("||||||||||||||||||||||||||||||||||||||");
|
|
1007
|
-
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
/**
|
|
1011
|
-
* Logs a http servlet response.
|
|
1012
|
-
*
|
|
1013
|
-
* @param context the golf context for this request
|
|
1014
|
-
*/
|
|
1015
|
-
private void logResponse(GolfContext context, int status) {
|
|
1016
|
-
String method = String.valueOf(status);
|
|
1017
|
-
String path = context.urlHash;
|
|
1018
|
-
String query = context.request.getQueryString();
|
|
1019
|
-
String host = context.request.getRemoteHost();
|
|
1020
|
-
String sid = context.request.getSession().getId();
|
|
1021
|
-
|
|
1022
|
-
String line = method + " " + path + (query != null ? "?" + query : "");
|
|
1023
|
-
|
|
1024
|
-
log(context, LOG_INFO, line);
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
/**
|
|
1028
|
-
* Convenience function to do html entity encoding.
|
|
1029
|
-
*
|
|
1030
|
-
* @param s the string to encode
|
|
1031
|
-
* @return the encoded string
|
|
1032
|
-
*/
|
|
1033
|
-
public static String HTMLEntityEncode(String s) {
|
|
1034
|
-
StringBuffer buf = new StringBuffer();
|
|
1035
|
-
int len = (s == null ? -1 : s.length());
|
|
1036
|
-
|
|
1037
|
-
for ( int i = 0; i < len; i++ ) {
|
|
1038
|
-
char c = s.charAt( i );
|
|
1039
|
-
if ( c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' ) {
|
|
1040
|
-
buf.append( c );
|
|
1041
|
-
} else {
|
|
1042
|
-
buf.append("&#" + (int)c + ";");
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
return buf.toString();
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
/**
|
|
1050
|
-
*
|
|
1051
|
-
*/
|
|
1052
|
-
public static String proxyURLEncode(String s) {
|
|
1053
|
-
return s.replaceAll("#", "%23");
|
|
1054
|
-
}
|
|
1055
|
-
}
|