From 9155e5f4f9d9d1d6746e451136f4d1e1ceba1dcc Mon Sep 17 00:00:00 2001 From: gojomo Date: Thu, 14 May 2009 21:19:24 +0000 Subject: [PATCH] copying noah's work to h3 Fix for [HER-1506] ByteReplayCharSequence ignores specified/non-default character encodings, reported by Jean-No?\195?\171l Rivasseau * RecordingOutputStream.java use ByteReplayCharSequence only for iso8859-1 * ReplayCharSequenceTest.java new tests for iso8859-1, windows-1252 and ascii --- .../org/archive/io/RecordingOutputStream.java | 11 ++-- .../archive/io/ReplayCharSequenceTest.java | 51 +++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/commons/src/main/java/org/archive/io/RecordingOutputStream.java b/commons/src/main/java/org/archive/io/RecordingOutputStream.java index b0358d9f..0537fe38 100644 --- a/commons/src/main/java/org/archive/io/RecordingOutputStream.java +++ b/commons/src/main/java/org/archive/io/RecordingOutputStream.java @@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.io.FastBufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.logging.Level; @@ -515,6 +516,8 @@ public class RecordingOutputStream extends OutputStream { return getReplayCharSequence(characterEncoding, this.contentBeginMark); } + private static final String canonicalLatin1 = Charset.forName("iso8859-1").name(); + /** * @param characterEncoding Encoding of recorded stream. * @return A ReplayCharSequence Will return null if an IOException. Call @@ -523,11 +526,11 @@ public class RecordingOutputStream extends OutputStream { */ public ReplayCharSequence getReplayCharSequence(String characterEncoding, long startOffset) throws IOException { + if (characterEncoding == null) { + characterEncoding = Charset.defaultCharset().name(); + } // TODO: handled transfer-encoding: chunked content-bodies properly - float maxBytesPerChar = IoUtils.encodingMaxBytesPerChar(characterEncoding); - if(maxBytesPerChar<=1) { - // single - // TODO: take into account single-byte encoding may be non-default + if (canonicalLatin1.equals(Charset.forName(characterEncoding).name())) { return new Latin1ByteReplayCharSequence( this.buffer, this.size, diff --git a/commons/src/test/java/org/archive/io/ReplayCharSequenceTest.java b/commons/src/test/java/org/archive/io/ReplayCharSequenceTest.java index 614e05cb..32e20bb9 100644 --- a/commons/src/test/java/org/archive/io/ReplayCharSequenceTest.java +++ b/commons/src/test/java/org/archive/io/ReplayCharSequenceTest.java @@ -158,6 +158,57 @@ public class ReplayCharSequenceTest extends TmpDirTestCase assertEquals("Strings don't match",result,fileContent); } + private String toHexString(String str) + { + if (str != null) { + StringBuilder buf = new StringBuilder("{ "); + buf.append(Integer.toString(str.charAt(0), 16)); + for (int i = 1; i < str.length(); i++) { + buf.append(", "); + buf.append(Integer.toString(str.charAt(i), 16)); + } + buf.append(" }"); + return buf.toString(); + } + else + return "null"; + } + + public void testSingleByteEncodings() throws IOException { + byte[] bytes = { + (byte) 0x61, (byte) 0x62, (byte) 0x63, (byte) 0x64, + (byte) 0x7d, (byte) 0x7e, (byte) 0x7f, (byte) 0x80, + (byte) 0x81, (byte) 0x82, (byte) 0x83, (byte) 0x84, + (byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff }; + + String latin1String = new String(bytes, "latin1"); + RecordingOutputStream ros = writeTestStream( + bytes, 1, "testSingleByteEncodings-latin1.txt", 0); + ReplayCharSequence rcs = ros.getReplayCharSequence("latin1"); + String result = rcs.toString(); + logger.info("latin1[0] " + toHexString(latin1String)); + logger.info("latin1[1] " + toHexString(result)); + assertEquals("latin1 strings don't match", result, latin1String); + + String w1252String = new String(bytes, "windows-1252"); + ros = writeTestStream( + bytes, 1, "testSingleByteEncodings-windows-1252.txt", 0); + rcs = ros.getReplayCharSequence("windows-1252"); + result = rcs.toString(); + logger.info("windows-1252[0] " + toHexString(w1252String)); + logger.info("windows-1252[1] " + toHexString(result)); + assertEquals("windows-1252 strings don't match", result, w1252String); + + String asciiString = new String(bytes, "ascii"); + ros = writeTestStream( + bytes, 1, "testSingleByteEncodings-ascii.txt", 0); + rcs = ros.getReplayCharSequence("ascii"); + result = rcs.toString(); + logger.info("ascii[0] " + toHexString(asciiString)); + logger.info("ascii[1] " + toHexString(result)); + assertEquals("ascii strings don't match", result, asciiString); + } + public void testReplayCharSequenceByteToStringOverflow() throws IOException { String fileContent = "Some file content. "; byte [] buffer = fileContent.getBytes();