19 package org.sleuthkit.autopsy.keywordsearch;
 
   21 import java.io.IOException;
 
   22 import java.io.InputStream;
 
   23 import java.nio.charset.Charset;
 
   41 class AbstractFileStringStream 
extends InputStream {
 
   44     private AbstractFile content;
 
   45     private Charset outputCharset;
 
   47     private static final Logger logger = Logger.getLogger(AbstractFileStringStream.class.getName());
 
   48     private static final String NLS = Character.toString((
char) 10); 
 
   49     private static final int READ_BUF_SIZE = 256;
 
   50     private long contentOffset = 0; 
 
   51     private final byte[] curReadBuf = 
new byte[READ_BUF_SIZE];
 
   52     private int bytesInReadBuf = 0;
 
   53     private int readBufOffset = 0; 
 
   54     private StringBuilder curString = 
new StringBuilder();
 
   55     private int curStringLen = 0;
 
   56     private StringBuilder tempString = 
new StringBuilder();
 
   57     private int tempStringLen = 0;
 
   58     private boolean isEOF = 
false;
 
   59     private boolean stringAtTempBoundary = 
false; 
 
   60     private boolean stringAtBufBoundary = 
false; 
 
   61     private boolean inString = 
false; 
 
   62     private final byte[] oneCharBuf = 
new byte[1];
 
   63     private final int MIN_PRINTABLE_CHARS = 4; 
 
   76     public AbstractFileStringStream(AbstractFile content, Charset outputCharset, 
boolean preserveOnBuffBoundary) {
 
   77         this.content = content;
 
   78         this.outputCharset = outputCharset;
 
   91     public AbstractFileStringStream(AbstractFile content, Charset outCharset) {
 
   92         this(content, outCharset, 
false);
 
   96     public int read(byte[] b, 
int off, 
int len) 
throws IOException {
 
   98             throw new NullPointerException();
 
   99         } 
else if (off < 0 || len < 0 || len > b.length - off) {
 
  100             throw new IndexOutOfBoundsException();
 
  101         } 
else if (len == 0) {
 
  105         long fileSize = content.getSize();
 
  114         if (stringAtTempBoundary) {
 
  119             stringAtTempBoundary = 
false;
 
  123         boolean singleConsecZero = 
false; 
 
  124         int newCurLen = curStringLen + tempStringLen;
 
  126         while (newCurLen < len) {
 
  128             if (readBufOffset > bytesInReadBuf - 1) {
 
  132                     bytesInReadBuf = content.read(curReadBuf, contentOffset, READ_BUF_SIZE);
 
  133                 } 
catch (TskException ex) {
 
  134                     if (curStringLen > 0 || tempStringLen >= MIN_PRINTABLE_CHARS) {
 
  138                         int copied = copyToReturn(b, off, len);
 
  144                 if (bytesInReadBuf < 1) {
 
  145                     if (curStringLen > 0 || tempStringLen >= MIN_PRINTABLE_CHARS) {
 
  149                         int copied = copyToReturn(b, off, len);
 
  156                 contentOffset += bytesInReadBuf;
 
  161             char c = (char) curReadBuf[readBufOffset++];
 
  162             if (c == 0 && singleConsecZero == 
false) {
 
  164                 singleConsecZero = 
true;
 
  166                 singleConsecZero = 
false;
 
  168             if (StringExtract.isPrintableAscii(c)) {
 
  169                 tempString.append(c);
 
  171                 if (tempStringLen >= MIN_PRINTABLE_CHARS) {
 
  176             } 
else if (!singleConsecZero) {
 
  178                 if (tempStringLen >= MIN_PRINTABLE_CHARS
 
  179                         || stringAtBufBoundary) {
 
  181                     tempString.append(NLS);
 
  184                     curString.append(tempString);
 
  185                     curStringLen += tempStringLen;
 
  187                     stringAtBufBoundary = 
false;
 
  190                 tempString = 
new StringBuilder();
 
  194             newCurLen = curStringLen + tempStringLen;
 
  201             stringAtBufBoundary = 
true; 
 
  207         if (tempStringLen >= MIN_PRINTABLE_CHARS) {
 
  208             if (newCurLen > len) {
 
  209                 int appendChars = len - curStringLen;
 
  212                 String toAppend = tempString.substring(0, appendChars);
 
  213                 String newTemp = tempString.substring(appendChars);
 
  215                 curString.append(toAppend);
 
  216                 curStringLen += appendChars;
 
  218                 tempString = 
new StringBuilder(newTemp);
 
  219                 tempStringLen = newTemp.length();
 
  221                 stringAtTempBoundary = 
true;
 
  225                 curString.append(tempString);
 
  226                 curStringLen += tempStringLen;
 
  229                 tempString = 
new StringBuilder();
 
  239         final int copied = copyToReturn(b, off, len);
 
  247     private void appendResetTemp() {
 
  248         if (tempStringLen >= MIN_PRINTABLE_CHARS) {
 
  249             curString.append(tempString);
 
  250             curStringLen += tempStringLen;
 
  251             tempString = 
new StringBuilder();
 
  258     private int copyToReturn(byte[] b, 
int off, 
long len) {
 
  260         final String curStringS = curString.toString();
 
  262         byte[] stringBytes = curStringS.getBytes(outputCharset);
 
  263         System.arraycopy(stringBytes, 0, b, off, Math.min(curStringLen, (
int) len));
 
  266         curString = 
new StringBuilder();
 
  267         int ret = curStringLen;
 
  274     public int read() throws IOException {
 
  275         final int read = read(oneCharBuf, 0, 1);
 
  277             return oneCharBuf[0];
 
  285     public int available() throws IOException {
 
  291     public long skip(
long n) 
throws IOException {
 
  294         return super.skip(n);