/** Returns {@code s} with control characters and non-ASCII characters replaced with '?'. */ private static String toHumanReadableAscii(String s) { for (int i = 0, length = s.length(), c; i < length; i += Character.charCount(c)) { c = s.codePointAt(i); if (c > '\u001f' && c < '\u007f') continue; Buffer buffer = new Buffer(); buffer.writeUtf8(s, 0, i); buffer.writeUtf8CodePoint('?'); for (int j = i + Character.charCount(c); j < length; j += Character.charCount(c)) { c = s.codePointAt(j); buffer.writeUtf8CodePoint(c > '\u001f' && c < '\u007f' ? c : '?'); } return buffer.readUtf8(); } return s; }
/** * Sets the response body to the UTF-8 encoded bytes of {@code body}, chunked every {@code * maxChunkSize} bytes. */ public MockResponse setChunkedBody(String body, int maxChunkSize) { return setChunkedBody(new Buffer().writeUtf8(body), maxChunkSize); }
/** Sets the response body to the UTF-8 encoded bytes of {@code body}. */ public MockResponse setBody(String body) { return setBody(new Buffer().writeUtf8(body)); }
static String percentDecode(String encoded, int pos, int limit, boolean plusIsSpace) { for (int i = pos; i < limit; i++) { char c = encoded.charAt(i); if (c == '%' || (c == '+' && plusIsSpace)) { // Slow path: the character at i requires decoding! Buffer out = new Buffer(); out.writeUtf8(encoded, pos, i); percentDecode(out, encoded, i, limit, plusIsSpace); return out.readUtf8(); } } // Fast path: no characters in [pos..limit) required decoding. return encoded.substring(pos, limit); }
private static String canonicalizeForPath(String input, boolean alreadyEncoded) { int codePoint; for (int i = 0, limit = input.length(); i < limit; i += Character.charCount(codePoint)) { codePoint = input.codePointAt(i); if (codePoint < 0x20 || codePoint >= 0x7f || PATH_SEGMENT_ALWAYS_ENCODE_SET.indexOf(codePoint) != -1 || (!alreadyEncoded && (codePoint == '/' || codePoint == '%'))) { // Slow path: the character at i requires encoding! Buffer out = new Buffer(); out.writeUtf8(input, 0, i); canonicalizeForPath(out, input, i, limit, alreadyEncoded); return out.readUtf8(); } } // Fast path: no characters required encoding. return input; }
/** * Returns the concatenation of 8-bit, length prefixed protocol names. * http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4 */ static byte[] concatLengthPrefixed(List<Protocol> protocols) { Buffer result = new Buffer(); for (int i = 0, size = protocols.size(); i < size; i++) { Protocol protocol = protocols.get(i); if (protocol == Protocol.HTTP_1_0) continue; // No HTTP/1.0 for ALPN. result.writeByte(protocol.toString().length()); result.writeUtf8(protocol.toString()); } return result.readByteArray(); }
/** * Sets the response body to {@code body}, chunked every {@code maxChunkSize} bytes. */ public MockResponse setChunkedBody(Buffer body, int maxChunkSize) { removeHeader("Content-Length"); headers.add(CHUNKED_BODY_HEADER); Buffer bytesOut = new Buffer(); while (!body.exhausted()) { long chunkSize = Math.min(body.size(), maxChunkSize); bytesOut.writeHexadecimalUnsignedLong(chunkSize); bytesOut.writeUtf8("\r\n"); bytesOut.write(body, chunkSize); bytesOut.writeUtf8("\r\n"); } bytesOut.writeUtf8("0\r\n"); // Last chunk. Trailers follow! this.body = bytesOut; return this; }
/** * Either writes this request to {@code sink} or measures its content length. We have one method * do double-duty to make sure the counting and content are consistent, particularly when it comes * to awkward operations like measuring the encoded length of header strings, or the * length-in-digits of an encoded integer. */ private long writeOrCountBytes(@Nullable BufferedSink sink, boolean countBytes) { long byteCount = 0L; Buffer buffer; if (countBytes) { buffer = new Buffer(); } else { buffer = sink.buffer(); } for (int i = 0, size = encodedNames.size(); i < size; i++) { if (i > 0) buffer.writeByte('&'); buffer.writeUtf8(encodedNames.get(i)); buffer.writeByte('='); buffer.writeUtf8(encodedValues.get(i)); } if (countBytes) { byteCount = buffer.size(); buffer.clear(); } return byteCount; }
@Test public void detectedWebPFile() throws Exception { assertThat(isWebPFile(new Buffer().writeUtf8("RIFFxxxxWEBP"))).isTrue(); assertThat(isWebPFile(new Buffer().writeUtf8("RIFFxxxxxWEBP"))).isFalse(); assertThat(isWebPFile(new Buffer().writeUtf8("ABCDxxxxWEBP"))).isFalse(); assertThat(isWebPFile(new Buffer().writeUtf8("RIFFxxxxABCD"))).isFalse(); assertThat(isWebPFile(new Buffer().writeUtf8("RIFFxxWEBP"))).isFalse(); }
@Test public void readableChannelBuffer() throws Exception { Buffer buffer = new Buffer(); buffer.writeUtf8("abcdefghijklmnopqrstuvwxyz"); testReadableByteChannel(buffer); }
public static ByteString encodeQuery(String host, int type) { Buffer buf = new Buffer(); buf.writeShort(0); // query id buf.writeShort(256); // flags with recursion buf.writeShort(1); // question count buf.writeShort(0); // answerCount buf.writeShort(0); // authorityResourceCount buf.writeShort(0); // additional Buffer nameBuf = new Buffer(); final String[] labels = host.split("\\."); for (String label : labels) { long utf8ByteCount = Utf8.size(label); if (utf8ByteCount != label.length()) { throw new IllegalArgumentException("non-ascii hostname: " + host); } nameBuf.writeByte((byte) utf8ByteCount); nameBuf.writeUtf8(label); } nameBuf.writeByte(0); // end nameBuf.copyTo(buf, 0, nameBuf.size()); buf.writeShort(type); buf.writeShort(1); // CLASS_IN return buf.readByteString(); }
@Test public void completeSegmentByteCountOnBufferWithFullSegments() { Buffer buffer = new Buffer(); buffer.writeUtf8(repeat('a', SEGMENT_SIZE * 4)); assertEquals(SEGMENT_SIZE * 4, buffer.completeSegmentByteCount()); }
@Test public void writeToSpanningSegments() throws Exception { Buffer buffer = new Buffer(); buffer.writeUtf8(repeat('a', SEGMENT_SIZE * 2)); buffer.writeUtf8(repeat('b', SEGMENT_SIZE * 2)); ByteArrayOutputStream out = new ByteArrayOutputStream(); buffer.skip(10); buffer.writeTo(out, SEGMENT_SIZE * 3); assertEquals(repeat('a', SEGMENT_SIZE * 2 - 10) + repeat('b', SEGMENT_SIZE + 10), out.toString()); assertEquals(repeat('b', SEGMENT_SIZE - 10), buffer.readUtf8(buffer.size())); }
@Test public void writeSourcePropagatesEof() throws IOException { Source source = new Buffer().writeUtf8("abcd"); try { sink.write(source, 8); fail(); } catch (EOFException expected) { } // Ensure that whatever was available was correctly written. sink.flush(); assertEquals("abcd", data.readUtf8()); }
@Test public void multipleSegmentsWithoutCompression() throws IOException { Buffer buffer = new Buffer(); Deflater deflater = new Deflater(); deflater.setLevel(Deflater.NO_COMPRESSION); DeflaterSink deflaterSink = new DeflaterSink(buffer, deflater); int byteCount = SEGMENT_SIZE * 4; deflaterSink.write(new Buffer().writeUtf8(repeat('a', byteCount)), byteCount); deflaterSink.close(); assertEquals(repeat('a', byteCount), inflate(buffer).readUtf8(byteCount)); }
@Test public void moveAllRequestedBytesWithRead() throws Exception { Buffer sink = new Buffer(); sink.writeUtf8(repeat('a', 10)); Buffer source = new Buffer(); source.writeUtf8(repeat('b', 15)); assertEquals(10, source.read(sink, 10)); assertEquals(20, sink.size()); assertEquals(5, source.size()); assertEquals(repeat('a', 10) + repeat('b', 10), sink.readUtf8(20)); }
@Test public void md5() throws Exception { HashingSink hashingSink = HashingSink.md5(sink); source.writeUtf8("abc"); hashingSink.write(source, 3L); assertEquals(MD5_abc, hashingSink.hash()); }
@Test public void hmacSha512() throws Exception { HashingSink hashingSink = HashingSink.hmacSha512(sink, HMAC_KEY); source.writeUtf8("abc"); hashingSink.write(source, 3L); assertEquals(HMAC_SHA512_abc, hashingSink.hash()); }
@Test public void writeAll() throws Exception { Buffer source = new Buffer().writeUtf8("abcdef"); assertEquals(6, sink.writeAll(source)); assertEquals(0, source.size()); sink.flush(); assertEquals("abcdef", data.readUtf8()); }
@Test public void readExhaustedSource() throws Exception { Buffer sink = new Buffer(); sink.writeUtf8(repeat('a', 10)); assertEquals(-1, source.read(sink, 10)); assertEquals(10, sink.size()); assertTrue(source.exhausted()); }