001 /* 002 * LAPIS lightweight structured text processing system 003 * 004 * Copyright (C) 1998-2002 Carnegie Mellon University, 005 * Copyright (C) 2003 Massachusetts Institute of Technology. 006 * All rights reserved. 007 * 008 * This library is free software; you can redistribute it 009 * and/or modify it under the terms of the GNU General 010 * Public License as published by the Free Software 011 * Foundation, version 2. 012 * 013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/ 014 */ 015 016 package lapisx.net; 017 018 import java.io.*; 019 020 public class ContentTypeGuessingReader extends Reader { 021 public static lapisx.util.Debug debug = lapisx.util.Debug.QUIET; 022 String contentType; 023 char[] head = new char[200]; 024 int start, end; 025 Reader tail; 026 027 public ContentTypeGuessingReader (Reader in) throws IOException { 028 start = 0; 029 end = in.read (head); 030 tail = in; 031 if (end == -1) 032 return; 033 034 String strHeader = new String (head, start, end); 035 strHeader = strHeader.trim (); 036 strHeader = strHeader.toLowerCase (); 037 debug.println ("CTGR read '" + strHeader + "'"); 038 039 if (strHeader.startsWith ("<html>") 040 || strHeader.startsWith ("<!doctype html") 041 || strHeader.startsWith ("<title>") // for directories 042 ) { 043 contentType = "text/html"; 044 } else if (strHeader.startsWith ("content-type:")) { 045 // Scan for newline (marking end of Content-type field); 046 // then scan for double newline (marking end of header) so we can 047 // omit the header from the document 048 StringBuffer typebuf = new StringBuffer (); 049 boolean readingContentType = true; 050 boolean sawNewline = false; 051 for (int i = "content-type:".length (); true; ++i) { 052 if (i >= end) { 053 end = in.read (head); 054 if (end <= 0) { 055 end = 0; 056 break; 057 } 058 i = 0; 059 } 060 char c = head[i]; 061 if (c == '\n') { 062 readingContentType = false; 063 if (sawNewline) { 064 start = i+1; 065 break; 066 } 067 else 068 sawNewline = true; 069 } else if (c != '\r') { 070 sawNewline = false; 071 if (readingContentType) 072 typebuf.append (c); 073 } 074 } 075 076 contentType = typebuf.toString (); 077 contentType = contentType.trim (); 078 } 079 debug.println ("CTGR guessed content-type " + contentType); 080 } 081 082 public String getContentType () { 083 return contentType; 084 } 085 086 public int read () throws IOException { 087 if (start < end) 088 return head[++start]; 089 else 090 return tail.read (); 091 } 092 093 public int read (char[] b) throws IOException { 094 return read (b, 0, b.length); 095 } 096 097 public int read (char[] b, int off, int len) throws IOException { 098 if (start < end) { 099 int n = Math.min (end-start, len); 100 System.arraycopy (head, start, b, off, n); 101 start += n; 102 103 if (n < len) { 104 int n2 = tail.read (b, off+n, len-n); 105 if (n2 >= 0) 106 n += n2; 107 } 108 return n; 109 } 110 else 111 return tail.read (b, off, len); 112 } 113 114 public long skip (long n) throws IOException { 115 if (start < end) { 116 long n2 = Math.min ((long) (end-start), n); 117 start += (int)n2; 118 119 if (n2 < n) 120 n2 += tail.skip (n - n2); 121 return n2; 122 } 123 else 124 return tail.skip (n); 125 } 126 127 public boolean ready () throws IOException { 128 return (end > start) || tail.ready (); 129 } 130 131 public void close () throws IOException { 132 tail.close (); 133 } 134 135 public void mark (int readlimit) { 136 } 137 138 public void reset () throws IOException { 139 throw new IOException ("reset not supported"); 140 } 141 142 public boolean markSupported () { 143 return false; 144 } 145 }