@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(); }
@Override public int realReadChars(char cbuf[], int off, int len) throws IOException { if (!gotEnc) { setConverter(); } boolean eof = false; if (bb.getLength() <= 0) { int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length); if (nRead < 0) { eof = true; } } if (markPos == -1) { cb.setOffset(0); cb.setEnd(0); } else { // Make sure there's enough space in the worst case cb.makeSpace(bb.getLength()); if ((cb.getBuffer().length - cb.getEnd()) == 0) { // We went over the limit cb.setOffset(0); cb.setEnd(0); markPos = -1; } } state = CHAR_STATE; conv.convert(bb, cb, eof); if (cb.getLength() == 0 && eof) { return -1; } else { return cb.getLength(); } }
/* * 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); } } }
/** * Since the converter will use append, it is possible to get chars to be removed from the buffer * for "writing". Since the chars have already been read before, they are ignored. If a mark was * set, then the mark is lost. */ @Override public void realWriteChars(char c[], int off, int len) throws IOException { markPos = -1; cb.setOffset(0); cb.setEnd(0); }