@Override public long skip(long n) throws IOException { if (closed) { throw new IOException(sm.getString("inputBuffer.streamClosed")); } if (n < 0) { throw new IllegalArgumentException(); } long nRead = 0; while (nRead < n) { if (cb.getLength() >= n) { cb.setOffset(cb.getStart() + (int) n); nRead = n; } else { nRead += cb.getLength(); cb.setOffset(cb.getEnd()); int toRead = 0; if (cb.getChars().length < (n - nRead)) { toRead = cb.getChars().length; } else { toRead = (int) (n - nRead); } int nb = realReadChars(cb.getChars(), 0, toRead); if (nb < 0) { break; } } } return nRead; }
@Override public void mark(int readAheadLimit) throws IOException { if (closed) { throw new IOException(sm.getString("inputBuffer.streamClosed")); } if (cb.getLength() <= 0) { cb.setOffset(0); cb.setEnd(0); } else { if ((cb.getBuffer().length > (2 * size)) && (cb.getLength()) < (cb.getStart())) { System.arraycopy(cb.getBuffer(), cb.getStart(), cb.getBuffer(), 0, cb.getLength()); cb.setEnd(cb.getLength()); cb.setOffset(0); } } cb.setLimit(cb.getStart() + readAheadLimit + size); markPos = cb.getStart(); }
/** * Check that the URI is normalized following character decoding. * * <p>This method checks for "\", 0, "//", "/./" and "/../". This method will return false if * sequences that are supposed to be normalized are still present in the URI. * * @param uriMB URI to be checked (should be chars) */ public static boolean checkNormalize(MessageBytes uriMB) { CharChunk uriCC = uriMB.getCharChunk(); char[] c = uriCC.getChars(); int start = uriCC.getStart(); int end = uriCC.getEnd(); int pos = 0; // Check for '\' and 0 for (pos = start; pos < end; pos++) { if (c[pos] == '\\') { return false; } if (c[pos] == 0) { return false; } } // Check for "//" for (pos = start; pos < (end - 1); pos++) { if (c[pos] == '/') { if (c[pos + 1] == '/') { return false; } } } // Check for ending with "/." or "/.." if (((end - start) >= 2) && (c[end - 1] == '.')) { if ((c[end - 2] == '/') || ((c[end - 2] == '.') && (c[end - 3] == '/'))) { return false; } } // Check for "/./" if (uriCC.indexOf("/./", 0, 3, 0) >= 0) { return false; } // Check for "/../" if (uriCC.indexOf("/../", 0, 4, 0) >= 0) { return false; } return true; }
/** Character conversion of the URI. */ protected void convertURI(MessageBytes uri, Request request) throws Exception { ByteChunk bc = uri.getByteChunk(); int length = bc.getLength(); CharChunk cc = uri.getCharChunk(); cc.allocate(length, -1); String enc = connector.getURIEncoding(); if (enc != null) { B2CConverter conv = request.getURIConverter(); try { if (conv == null) { conv = new B2CConverter(enc, true); request.setURIConverter(conv); } else { conv.recycle(); } } catch (IOException e) { log.error("Invalid URI encoding; using HTTP default"); connector.setURIEncoding(null); } if (conv != null) { try { conv.convert(bc, cc, true); uri.setChars(cc.getBuffer(), cc.getStart(), cc.getLength()); return; } catch (IOException ioe) { // Should never happen as B2CConverter should replace // problematic characters request.getResponse().sendError(HttpServletResponse.SC_BAD_REQUEST); } } } // Default encoding: fast conversion for ISO-8859-1 byte[] bbuf = bc.getBuffer(); char[] cbuf = cc.getBuffer(); int start = bc.getStart(); for (int i = 0; i < length; i++) { cbuf[i] = (char) (bbuf[i + start] & 0xff); } uri.setChars(cbuf, 0, length); }
/* * Removes /./ and /../ sequences from absolute URLs. * Code borrowed heavily from CoyoteAdapter.normalize() */ private void normalize(CharChunk cc) { // Strip query string and/or fragment first as doing it this way makes // the normalization logic a lot simpler int truncate = cc.indexOf('?'); if (truncate == -1) { truncate = cc.indexOf('#'); } char[] truncateCC = null; if (truncate > -1) { truncateCC = Arrays.copyOfRange(cc.getBuffer(), cc.getStart() + truncate, cc.getEnd()); cc.setEnd(cc.getStart() + truncate); } if (cc.endsWith("/.") || cc.endsWith("/..")) { try { cc.append('/'); } catch (IOException e) { throw new IllegalArgumentException(cc.toString(), e); } } char[] c = cc.getChars(); int start = cc.getStart(); int end = cc.getEnd(); int index = 0; int startIndex = 0; // Advance past the first three / characters (should place index just // scheme://host[:port] for (int i = 0; i < 3; i++) { startIndex = cc.indexOf('/', startIndex + 1); } // Remove /./ index = startIndex; while (true) { index = cc.indexOf("/./", 0, 3, index); if (index < 0) { break; } copyChars(c, start + index, start + index + 2, end - start - index - 2); end = end - 2; cc.setEnd(end); } // Remove /../ index = startIndex; int pos; while (true) { index = cc.indexOf("/../", 0, 4, index); if (index < 0) { break; } // Can't go above the server root if (index == startIndex) { throw new IllegalArgumentException(); } int index2 = -1; for (pos = start + index - 1; (pos >= 0) && (index2 < 0); pos--) { if (c[pos] == (byte) '/') { index2 = pos; } } copyChars(c, start + index2, start + index + 3, end - start - index - 3); end = end + index2 - index - 3; cc.setEnd(end); index = index2; } // Add the query string and/or fragment (if present) back in if (truncateCC != null) { try { cc.append(truncateCC, 0, truncateCC.length); } catch (IOException ioe) { throw new IllegalArgumentException(ioe); } } }