1 28 29 package com.caucho.server.dispatch; 30 31 import com.caucho.config.ConfigException; 32 import com.caucho.i18n.CharacterEncoding; 33 import com.caucho.log.Log; 34 import com.caucho.server.util.CauchoSystem; 35 import com.caucho.util.CharBuffer; 36 import com.caucho.util.L10N; 37 import com.caucho.vfs.ByteToChar; 38 39 import java.io.IOException ; 40 import java.io.UnsupportedEncodingException ; 41 import java.util.logging.Level ; 42 import java.util.logging.Logger ; 43 44 47 public class InvocationDecoder { 48 static final Logger log = Log.open(InvocationDecoder.class); 49 static final L10N L = new L10N(InvocationDecoder.class); 50 51 private String _encoding = "UTF-8"; 53 54 private String _sessionCookie = "JSESSIONID"; 55 private String _sslSessionCookie; 56 57 private String _sessionSuffix = ";jsessionid="; 59 private char _sessionSuffixChar = ';'; 60 61 private String _sessionPrefix; 63 64 67 public InvocationDecoder() 68 { 69 _encoding = CharacterEncoding.getLocalEncoding(); 70 if (_encoding == null) 71 _encoding = "UTF-8"; 72 } 73 74 77 public String getEncoding() 78 { 79 return _encoding; 80 } 81 82 85 public void setEncoding(String encoding) 86 { 87 _encoding = encoding; 88 } 89 90 93 public void setSessionCookie(String cookie) 94 { 95 _sessionCookie = cookie; 96 } 97 98 101 public String getSessionCookie() 102 { 103 return _sessionCookie; 104 } 105 106 109 public void setSSLSessionCookie(String cookie) 110 { 111 _sslSessionCookie = cookie; 112 } 113 114 117 public String getSSLSessionCookie() 118 { 119 if (_sslSessionCookie != null) 120 return _sslSessionCookie; 121 else 122 return _sessionCookie; 123 } 124 125 128 public void setSessionURLPrefix(String prefix) 129 { 130 _sessionSuffix = prefix; 131 if (_sessionSuffix != null) 132 _sessionSuffixChar = _sessionSuffix.charAt(0); 133 } 134 135 138 public String getSessionURLPrefix() 139 { 140 return _sessionSuffix; 141 } 142 143 146 public void setAlternateSessionURLPrefix(String prefix) 147 throws ConfigException 148 { 149 if (! prefix.startsWith("/")) 150 prefix = '/' + prefix; 151 152 if (prefix.lastIndexOf('/') > 0) 153 throw new ConfigException(L.l("`{0}' is an invalidate alternate-session-url-prefix. The url-prefix must not have any embedded '/'.", prefix)); 154 155 _sessionPrefix = prefix; 156 _sessionSuffix = null; 157 } 158 159 162 public String getAlternateSessionURLPrefix() 163 { 164 return _sessionPrefix; 165 } 166 167 170 public void splitQueryAndUnescape(Invocation invocation, 171 byte []rawURI, int uriLength) 172 throws IOException 173 { 174 for (int i = 0; i < uriLength; i++) { 175 if (rawURI[i] == '?') { 176 i++; 177 178 String queryString = byteToChar(rawURI, i, uriLength - i, 180 "ISO-8859-1"); 181 invocation.setQueryString(queryString); 182 183 uriLength = i - 1; 184 break; 185 } 186 } 187 188 String rawURIString = byteToChar(rawURI, 0, uriLength, "ISO-8859-1"); 189 invocation.setRawURI(rawURIString); 190 191 String decodedURI = normalizeUriEscape(rawURI, 0, uriLength, _encoding); 192 193 if (_sessionSuffix != null) { 194 int p = decodedURI.indexOf(_sessionSuffix); 195 196 if (p >= 0) { 197 int suffixLength = _sessionSuffix.length(); 198 int tail = decodedURI.indexOf(';', p + suffixLength); 199 String sessionId; 200 201 if (tail > 0) 202 sessionId = decodedURI.substring(p + suffixLength, tail); 203 else 204 sessionId = decodedURI.substring(p + suffixLength); 205 206 decodedURI = decodedURI.substring(0, p); 207 208 invocation.setSessionId(sessionId); 209 210 p = rawURIString.indexOf(_sessionSuffix); 211 if (p > 0) { 212 rawURIString = rawURIString.substring(0, p); 213 invocation.setRawURI(rawURIString); 214 } 215 } 216 } 217 else if (_sessionPrefix != null) { 218 if (decodedURI.startsWith(_sessionPrefix)) { 219 int prefixLength = _sessionPrefix.length(); 220 221 int tail = decodedURI.indexOf('/', prefixLength); 222 String sessionId; 223 224 if (tail > 0) { 225 sessionId = decodedURI.substring(prefixLength, tail); 226 decodedURI = decodedURI.substring(tail); 227 invocation.setRawURI(rawURIString.substring(tail)); 228 } 229 else { 230 sessionId = decodedURI.substring(prefixLength); 231 decodedURI = "/"; 232 invocation.setRawURI("/"); 233 } 234 235 invocation.setSessionId(sessionId); 236 } 237 } 238 239 String uri = normalizeUri(decodedURI); 240 241 invocation.setURI(uri); 242 invocation.setContextURI(uri); 243 } 244 245 249 public void splitQuery(Invocation invocation, String rawURI) 250 throws IOException 251 { 252 int p = rawURI.indexOf('?'); 253 if (p > 0) { 254 invocation.setQueryString(rawURI.substring(p + 1)); 255 256 rawURI = rawURI.substring(0, p); 257 } 258 259 invocation.setRawURI(rawURI); 260 261 String uri = normalizeUri(rawURI); 262 263 invocation.setURI(uri); 264 invocation.setContextURI(uri); 265 } 266 267 270 public void normalizeURI(Invocation invocation, String rawURI) 271 throws IOException 272 { 273 invocation.setRawURI(rawURI); 274 275 String uri = normalizeUri(rawURI); 276 277 invocation.setURI(uri); 278 invocation.setContextURI(uri); 279 } 280 281 284 public void splitSession(Invocation invocation) 285 { 286 if (_sessionSuffix != null) { 287 String uri = invocation.getURI(); 288 } 289 else if (_sessionPrefix != null) { 290 String uri = invocation.getURI(); 291 } 292 } 293 294 private String byteToChar(byte []buffer, int offset, int length, 295 String encoding) 296 { 297 ByteToChar converter = ByteToChar.create(); 298 300 if (encoding == null) 301 encoding = "utf-8"; 302 303 try { 304 converter.setEncoding(encoding); 305 } catch (UnsupportedEncodingException e) { 306 log.log(Level.FINE, e.toString(), e); 307 } 308 309 try { 310 for (; length > 0; length--) 311 converter.addByte(buffer[offset++]); 312 313 return converter.getConvertedString(); 314 } catch (IOException e) { 315 return "unknown"; 316 } 317 } 318 319 325 public static String normalizeUri(String uri) 326 throws IOException 327 { 328 return normalizeUri(uri, CauchoSystem.isWindows()); 329 } 330 331 337 public static String normalizeUri(String uri, boolean isWindows) 338 throws IOException 339 { 340 CharBuffer cb = CharBuffer.allocate(); 341 342 int len = uri.length(); 343 344 if (len > 1024) 345 throw new BadRequestException(L.l("The request contains an illegal URL.")); 346 347 boolean isBogus; 348 char ch; 349 char ch1; 350 if (len == 0 || (ch = uri.charAt(0)) != '/' && ch != '\\') 351 cb.append('/'); 352 353 for (int i = 0; i < len; i++) { 354 ch = uri.charAt(i); 355 356 if (ch == '/' || ch == '\\') { 357 dots: 358 while (i + 1 < len) { 359 ch = uri.charAt(i + 1); 360 361 if (ch == '/' || ch == '\\') 362 i++; 363 else if (ch != '.') 364 break dots; 365 else if (i + 2 >= len || 366 (ch = uri.charAt(i + 2)) == '/' || ch == '\\') { 367 i += 2; 368 } 369 else if (ch != '.') 370 break dots; 371 else if (i + 3 >= len || 372 (ch = uri.charAt(i + 3)) == '/' || ch == '\\') { 373 int j; 374 375 for (j = cb.length() - 1; j >= 0; j--) { 376 if ((ch = cb.charAt(j)) == '/' || ch == '\\') 377 break; 378 } 379 if (j > 0) 380 cb.setLength(j); 381 else 382 cb.setLength(0); 383 i += 3; 384 } else { 385 throw new BadRequestException(L.l("The request contains an illegal URL.")); 386 } 387 } 388 389 while (isWindows && cb.getLength() > 0 && 390 ((ch = cb.getLastChar()) == '.' || ch == ' ')) { 391 cb.setLength(cb.getLength() - 1); 392 } 393 394 cb.append('/'); 395 } 396 else if (ch == 0) 397 throw new BadRequestException(L.l("The request contains an illegal URL.")); 398 else 399 cb.append(ch); 400 } 401 402 return cb.close(); 403 } 404 405 415 private static String normalizeUriEscape(byte []rawUri, int i, int len, 416 String encoding) 417 throws IOException 418 { 419 ByteToChar converter = ByteToChar.create(); 420 422 if (encoding == null) 423 encoding = "utf-8"; 424 425 try { 426 converter.setEncoding(encoding); 427 } catch (UnsupportedEncodingException e) { 428 log.log(Level.FINE, e.toString(), e); 429 } 430 431 try { 432 while (i < len) { 433 int ch = rawUri[i++] & 0xff; 434 435 if (ch == '%') 436 i = scanUriEscape(converter, rawUri, i, len); 437 else 438 converter.addByte(ch); 439 } 440 441 return converter.getConvertedString(); 442 } catch (Exception e) { 443 throw new BadRequestException(L.l("The URL contains escaped bytes unsupported by the {0} encoding.", encoding)); 444 } 445 } 446 447 457 private static int scanUriEscape(ByteToChar converter, 458 byte []rawUri, int i, int len) 459 throws IOException 460 { 461 int ch1 = i < len ? (rawUri[i++] & 0xff) : -1; 462 463 if (ch1 == 'u') { 464 ch1 = i < len ? (rawUri[i++] & 0xff) : -1; 465 int ch2 = i < len ? (rawUri[i++] & 0xff) : -1; 466 int ch3 = i < len ? (rawUri[i++] & 0xff) : -1; 467 int ch4 = i < len ? (rawUri[i++] & 0xff) : -1; 468 469 converter.addChar((char) ((toHex(ch1) << 12) + 470 (toHex(ch2) << 8) + 471 (toHex(ch3) << 4) + 472 (toHex(ch4)))); 473 } 474 else { 475 int ch2 = i < len ? (rawUri[i++] & 0xff) : -1; 476 477 int b = (toHex(ch1) << 4) + toHex(ch2);; 478 479 converter.addByte(b); 480 } 481 482 return i; 483 } 484 485 488 private static int toHex(int ch) 489 { 490 if (ch >= '0' && ch <= '9') 491 return ch - '0'; 492 else if (ch >= 'a' && ch <= 'f') 493 return ch - 'a' + 10; 494 else if (ch >= 'A' && ch <= 'F') 495 return ch - 'A' + 10; 496 else 497 return -1; 498 } 499 } 500 | Popular Tags |