diff options
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r-- | OpenSim/Framework/Servers/OSHttpHandler.cs | 22 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/OSHttpRequestPump.cs | 137 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/OSHttpXmlRpcHandler.cs | 79 |
3 files changed, 118 insertions, 120 deletions
diff --git a/OpenSim/Framework/Servers/OSHttpHandler.cs b/OpenSim/Framework/Servers/OSHttpHandler.cs index 8b65438..6e8f6fb 100644 --- a/OpenSim/Framework/Servers/OSHttpHandler.cs +++ b/OpenSim/Framework/Servers/OSHttpHandler.cs | |||
@@ -93,6 +93,16 @@ namespace OpenSim.Framework.Servers | |||
93 | protected Regex _path; | 93 | protected Regex _path; |
94 | 94 | ||
95 | /// <summary> | 95 | /// <summary> |
96 | /// Dictionary of (query name, regular expression) tuples, | ||
97 | /// allowing us to match on URI query fields. | ||
98 | /// </summary> | ||
99 | public virtual Dictionary<string, Regex> Query | ||
100 | { | ||
101 | get { return _query; } | ||
102 | } | ||
103 | protected Dictionary<string, Regex> _query; | ||
104 | |||
105 | /// <summary> | ||
96 | /// Dictionary of (header name, regular expression) tuples, | 106 | /// Dictionary of (header name, regular expression) tuples, |
97 | /// allowing us to match on HTTP header fields. | 107 | /// allowing us to match on HTTP header fields. |
98 | /// </summary> | 108 | /// </summary> |
@@ -119,18 +129,6 @@ namespace OpenSim.Framework.Servers | |||
119 | 129 | ||
120 | 130 | ||
121 | /// <summary> | 131 | /// <summary> |
122 | /// An OSHttpHandler that matches on the "content-type" header can | ||
123 | /// supply an OSHttpContentTypeChecker delegate which will be | ||
124 | /// invoked by the request matcher in OSHttpRequestPump. | ||
125 | /// </summary> | ||
126 | /// <returns>true if the handler is interested in the content; | ||
127 | /// false otherwise</returns> | ||
128 | internal virtual OSHttpContentTypeChecker ContentTypeChecker | ||
129 | { | ||
130 | get { return null; } | ||
131 | } | ||
132 | |||
133 | /// <summary> | ||
134 | /// Base class constructor. | 132 | /// Base class constructor. |
135 | /// </summary> | 133 | /// </summary> |
136 | /// <param name="path">null or path regex</param> | 134 | /// <param name="path">null or path regex</param> |
diff --git a/OpenSim/Framework/Servers/OSHttpRequestPump.cs b/OpenSim/Framework/Servers/OSHttpRequestPump.cs index d05e706..8d4dc0d 100644 --- a/OpenSim/Framework/Servers/OSHttpRequestPump.cs +++ b/OpenSim/Framework/Servers/OSHttpRequestPump.cs | |||
@@ -175,18 +175,13 @@ namespace OpenSim.Framework.Servers | |||
175 | _log.DebugFormat("[{0}] MatchHandlers for {1}", EngineID, req); | 175 | _log.DebugFormat("[{0}] MatchHandlers for {1}", EngineID, req); |
176 | foreach (OSHttpHandler h in handlers) | 176 | foreach (OSHttpHandler h in handlers) |
177 | { | 177 | { |
178 | Regex methodRegex = h.Method; | ||
179 | Regex pathRegex = h.Path; | ||
180 | Dictionary<string, Regex> headerRegexs = h.Headers; | ||
181 | Regex endPointsRegex = h.IPEndPointWhitelist; | ||
182 | |||
183 | // initial anchor | 178 | // initial anchor |
184 | scoredHandlers[h] = 0; | 179 | scoredHandlers[h] = 0; |
185 | 180 | ||
186 | // first, check whether IPEndPointWhitelist applies | 181 | // first, check whether IPEndPointWhitelist applies |
187 | // and, if it does, whether client is on that white | 182 | // and, if it does, whether client is on that white |
188 | // list. | 183 | // list. |
189 | if (null != endPointsRegex) | 184 | if (null != h.IPEndPointWhitelist) |
190 | { | 185 | { |
191 | // TODO: following code requires code changes to | 186 | // TODO: following code requires code changes to |
192 | // HttpServer.HttpRequest to become functional | 187 | // HttpServer.HttpRequest to become functional |
@@ -194,84 +189,65 @@ namespace OpenSim.Framework.Servers | |||
194 | IPEndPoint remote = req.RemoteIPEndPoint; | 189 | IPEndPoint remote = req.RemoteIPEndPoint; |
195 | if (null != remote) | 190 | if (null != remote) |
196 | { | 191 | { |
197 | Match epm = endPointsRegex.Match(remote.ToString()); | 192 | Match epm = h.IPEndPointWhitelist.Match(remote.ToString()); |
198 | if (!epm.Success) continue; | 193 | if (!epm.Success) |
194 | { | ||
195 | scoredHandlers.Remove(h); | ||
196 | continue; | ||
197 | } | ||
199 | } | 198 | } |
200 | } | 199 | } |
201 | 200 | ||
202 | if (null != methodRegex) | 201 | if (null != h.Method) |
203 | { | 202 | { |
204 | Match m = methodRegex.Match(req.HttpMethod); | 203 | Match m = h.Method.Match(req.HttpMethod); |
205 | if (!m.Success) continue; | 204 | if (!m.Success) |
206 | 205 | { | |
206 | scoredHandlers.Remove(h); | ||
207 | continue; | ||
208 | } | ||
207 | scoredHandlers[h]++; | 209 | scoredHandlers[h]++; |
208 | } | 210 | } |
209 | 211 | ||
210 | // whitelist ok, now check path | 212 | // whitelist ok, now check path |
211 | if (null != pathRegex) | 213 | if (null != h.Path) |
212 | { | 214 | { |
213 | Match m = pathRegex.Match(req.RawUrl); | 215 | Match m = h.Path.Match(req.RawUrl); |
214 | if (!m.Success) continue; | 216 | if (!m.Success) |
215 | 217 | { | |
216 | scoredHandlers[h] = m.ToString().Length; | 218 | scoredHandlers.Remove(h); |
219 | continue; | ||
220 | } | ||
221 | scoredHandlers[h] += m.ToString().Length; | ||
217 | } | 222 | } |
218 | 223 | ||
219 | // whitelist & path ok, now check headers | 224 | // whitelist & path ok, now check query string |
220 | if (null != headerRegexs) | 225 | if (null != h.Query) |
221 | { | 226 | { |
222 | int headersMatch = 0; | 227 | int queriesMatch = MatchOnNameValueCollection(req.QueryString, h.Query); |
223 | 228 | if (0 == queriesMatch) | |
224 | // go through all header Regexs and evaluate | ||
225 | // match: | ||
226 | // if header field not present or does not match: | ||
227 | // remove handler from scoredHandlers | ||
228 | // continue | ||
229 | // else: | ||
230 | // add increment headersMatch | ||
231 | NameValueCollection headers = req.HttpRequest.Headers; | ||
232 | foreach (string tag in headerRegexs.Keys) | ||
233 | { | 229 | { |
234 | // do we have a header "tag"? | 230 | _log.DebugFormat("[{0}] request {1}", EngineID, req); |
235 | if (null == headers[tag]) | 231 | _log.DebugFormat("[{0}] dropping handler {1}", EngineID, h); |
236 | { | ||
237 | // no: remove the handler if it was added | ||
238 | // earlier and on to the next one | ||
239 | _log.DebugFormat("[{0}] dropping handler for {1}: null {2} header field: {3}", EngineID, req, tag, h); | ||
240 | 232 | ||
241 | scoredHandlers.Remove(h); | 233 | scoredHandlers.Remove(h); |
242 | break; | ||
243 | } | ||
244 | |||
245 | // does the content of header "tag" match | ||
246 | // the supplied regex? | ||
247 | Match hm = headerRegexs[tag].Match(headers[tag]); | ||
248 | if (!hm.Success) { | ||
249 | // no: remove the handler if it was added | ||
250 | // earlier and on to the next one | ||
251 | _log.DebugFormat("[{0}] dropping handler for {1}: {2} header field content \"{3}\" does not match regex {4}: {5}", | ||
252 | EngineID, req, tag, headers[tag], headerRegexs[tag].ToString(), h); | ||
253 | scoredHandlers.Remove(h); | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | // if we are looking at the "content-type" tag, | ||
258 | // check wether h has a ContentTypeChecker and | ||
259 | // invoke it if it has | ||
260 | if ((null != h.ContentTypeChecker) && !h.ContentTypeChecker(req)) | ||
261 | { | ||
262 | scoredHandlers.Remove(h); | ||
263 | _log.DebugFormat("[{0}] dropping handler for {1}: content checker returned false: {2}", EngineID, req, h); | ||
264 | break; | ||
265 | } | ||
266 | |||
267 | // ok: header matches | ||
268 | headersMatch++; | ||
269 | _log.DebugFormat("[{0}] MatchHandlers: found handler for {1}: {2}", EngineID, req, h.ToString()); | ||
270 | continue; | 234 | continue; |
271 | } | 235 | } |
272 | // check whether h got kicked out | 236 | scoredHandlers[h] += queriesMatch; |
273 | if (!scoredHandlers.ContainsKey(h)) continue; | 237 | } |
238 | |||
239 | // whitelist, path, query string ok, now check headers | ||
240 | if (null != h.Headers) | ||
241 | { | ||
242 | int headersMatch = MatchOnNameValueCollection(req.Headers, h.Headers); | ||
243 | if (0 == headersMatch) | ||
244 | { | ||
245 | _log.DebugFormat("[{0}] request {1}", EngineID, req); | ||
246 | _log.DebugFormat("[{0}] dropping handler {1}", EngineID, h); | ||
274 | 247 | ||
248 | scoredHandlers.Remove(h); | ||
249 | continue; | ||
250 | } | ||
275 | scoredHandlers[h] += headersMatch; | 251 | scoredHandlers[h] += headersMatch; |
276 | } | 252 | } |
277 | } | 253 | } |
@@ -285,6 +261,33 @@ namespace OpenSim.Framework.Servers | |||
285 | return matchingHandlers; | 261 | return matchingHandlers; |
286 | } | 262 | } |
287 | 263 | ||
264 | protected int MatchOnNameValueCollection(NameValueCollection collection, Dictionary<string, Regex> regexs) | ||
265 | { | ||
266 | int matched = 0; | ||
267 | |||
268 | foreach (string tag in regexs.Keys) | ||
269 | { | ||
270 | // do we have a header "tag"? | ||
271 | if (null == collection[tag]) | ||
272 | { | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | // does the content of collection[tag] match | ||
277 | // the supplied regex? | ||
278 | Match cm = regexs[tag].Match(collection[tag]); | ||
279 | if (!cm.Success) { | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | // ok: matches | ||
284 | matched++; | ||
285 | continue; | ||
286 | } | ||
287 | |||
288 | return matched; | ||
289 | } | ||
290 | |||
288 | [ConditionalAttribute("DEBUGGING")] | 291 | [ConditionalAttribute("DEBUGGING")] |
289 | private void LogDumpHandlerList(List<OSHttpHandler> l) | 292 | private void LogDumpHandlerList(List<OSHttpHandler> l) |
290 | { | 293 | { |
diff --git a/OpenSim/Framework/Servers/OSHttpXmlRpcHandler.cs b/OpenSim/Framework/Servers/OSHttpXmlRpcHandler.cs index f9ce5b1..2c31cfd 100644 --- a/OpenSim/Framework/Servers/OSHttpXmlRpcHandler.cs +++ b/OpenSim/Framework/Servers/OSHttpXmlRpcHandler.cs | |||
@@ -51,48 +51,42 @@ namespace OpenSim.Framework.Servers | |||
51 | /// </summary> | 51 | /// </summary> |
52 | /// <returns>true if the handler is interested in the content; | 52 | /// <returns>true if the handler is interested in the content; |
53 | /// false otherwise</returns> | 53 | /// false otherwise</returns> |
54 | internal override OSHttpContentTypeChecker ContentTypeChecker | 54 | protected bool XmlRpcMethodMatch(OSHttpRequest req) |
55 | { | 55 | { |
56 | get | 56 | XmlRpcRequest xmlRpcRequest = null; |
57 | { | 57 | |
58 | return delegate(OSHttpRequest req) | 58 | // check whether req is already reified |
59 | // if not: reify (and post to whiteboard) | ||
60 | try | ||
61 | { | ||
62 | if (req.Whiteboard.ContainsKey("xmlrequest")) | ||
59 | { | 63 | { |
60 | XmlRpcRequest xmlRpcRequest = null; | 64 | xmlRpcRequest = req.Whiteboard["xmlrequest"] as XmlRpcRequest; |
61 | 65 | } | |
62 | // check whether req is already reified | 66 | else |
63 | // if not: reify (and post to whiteboard) | 67 | { |
64 | try | 68 | StreamReader body = new StreamReader(req.InputStream); |
65 | { | 69 | string requestBody = body.ReadToEnd(); |
66 | if (req.Whiteboard.ContainsKey("xmlrequest")) | 70 | xmlRpcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody); |
67 | { | 71 | req.Whiteboard["xmlrequest"] = xmlRpcRequest; |
68 | xmlRpcRequest = req.Whiteboard["xmlrequest"] as XmlRpcRequest; | 72 | } |
69 | } | 73 | } |
70 | else | 74 | catch (XmlException) |
71 | { | 75 | { |
72 | StreamReader body = new StreamReader(req.InputStream); | 76 | _log.ErrorFormat("[OSHttpXmlRpcHandler] failed to deserialize XmlRpcRequest from {0}", req.ToString()); |
73 | string requestBody = body.ReadToEnd(); | 77 | return false; |
74 | xmlRpcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody); | ||
75 | req.Whiteboard["xmlrequest"] = xmlRpcRequest; | ||
76 | } | ||
77 | } | ||
78 | catch (XmlException) | ||
79 | { | ||
80 | _log.ErrorFormat("[OSHttpXmlRpcHandler] failed to deserialize XmlRpcRequest from {0}", req.ToString()); | ||
81 | return false; | ||
82 | } | ||
83 | |||
84 | // check against methodName | ||
85 | if ((null != xmlRpcRequest) | ||
86 | && !String.IsNullOrEmpty(xmlRpcRequest.MethodName) | ||
87 | && xmlRpcRequest.MethodName == _methodName) | ||
88 | { | ||
89 | _log.DebugFormat("[OSHttpXmlRpcHandler] located handler {0} for {1}", _methodName, req.ToString()); | ||
90 | return true; | ||
91 | } | ||
92 | |||
93 | return false; | ||
94 | }; | ||
95 | } | 78 | } |
79 | |||
80 | // check against methodName | ||
81 | if ((null != xmlRpcRequest) | ||
82 | && !String.IsNullOrEmpty(xmlRpcRequest.MethodName) | ||
83 | && xmlRpcRequest.MethodName == _methodName) | ||
84 | { | ||
85 | _log.DebugFormat("[OSHttpXmlRpcHandler] located handler {0} for {1}", _methodName, req.ToString()); | ||
86 | return true; | ||
87 | } | ||
88 | |||
89 | return false; | ||
96 | } | 90 | } |
97 | 91 | ||
98 | // contains handler for processing XmlRpc Request | 92 | // contains handler for processing XmlRpc Request |
@@ -149,8 +143,11 @@ namespace OpenSim.Framework.Servers | |||
149 | XmlRpcResponse xmlRpcResponse; | 143 | XmlRpcResponse xmlRpcResponse; |
150 | string responseString; | 144 | string responseString; |
151 | 145 | ||
146 | // check whether we are interested in this request | ||
147 | if (!XmlRpcMethodMatch(request)) return OSHttpHandlerResult.Pass; | ||
148 | |||
149 | |||
152 | OSHttpResponse resp = new OSHttpResponse(request); | 150 | OSHttpResponse resp = new OSHttpResponse(request); |
153 | |||
154 | try | 151 | try |
155 | { | 152 | { |
156 | // reified XmlRpcRequest must still be on the whiteboard | 153 | // reified XmlRpcRequest must still be on the whiteboard |