first commit

This commit is contained in:
MaddoScientisto 2026-03-14 20:04:39 +01:00
commit 4d332ef662
27586 changed files with 3281783 additions and 0 deletions

View file

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.3.1 (Apple Computer, Inc.)

View file

@ -0,0 +1,126 @@
package com.oreilly.servlet;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public class Base64Decoder extends FilterInputStream {
private static final char[] chars = new char[] {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/' };
private static final int[] ints = new int[128];
private int charCount;
private int carryOver;
static {
for (int i = 0; i < 64; i++)
ints[chars[i]] = i;
}
public Base64Decoder(InputStream in) {
super(in);
}
public int read() throws IOException {
while (true) {
int x = this.in.read();
if (x == -1)
return -1;
if (!Character.isWhitespace((char)x)) {
this.charCount++;
if (x == 61)
return -1;
x = ints[x];
int mode = (this.charCount - 1) % 4;
if (mode == 0) {
this.carryOver = x & 0x3F;
return read();
}
if (mode == 1) {
int decoded = (this.carryOver << 2) + (x >> 4) & 0xFF;
this.carryOver = x & 0xF;
return decoded;
}
if (mode == 2) {
int decoded = (this.carryOver << 4) + (x >> 2) & 0xFF;
this.carryOver = x & 0x3;
return decoded;
}
if (mode == 3) {
int decoded = (this.carryOver << 6) + x & 0xFF;
return decoded;
}
return -1;
}
}
}
public int read(byte[] buf, int off, int len) throws IOException {
if (buf.length < len + off - 1)
throw new IOException("The input buffer is too small: " + len + " bytes requested starting at offset " + off + " while the buffer " + " is only " + buf.length + " bytes long.");
int i;
for (i = 0; i < len; i++) {
int x = read();
if (x == -1 && i == 0)
return -1;
if (x == -1)
break;
buf[off + i] = (byte)x;
}
return i;
}
public static String decode(String encoded) {
return new String(decodeToBytes(encoded));
}
public static byte[] decodeToBytes(String encoded) {
byte[] bytes = null;
try {
bytes = encoded.getBytes("8859_1");
} catch (UnsupportedEncodingException ignored) {}
Base64Decoder in = new Base64Decoder(new ByteArrayInputStream(bytes));
ByteArrayOutputStream out = new ByteArrayOutputStream((int)((double)bytes.length * 0.67D));
try {
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buf)) != -1)
out.write(buf, 0, bytesRead);
out.close();
return out.toByteArray();
} catch (IOException ignored) {
return null;
}
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: java Base64Decoder fileToDecode");
return;
}
Base64Decoder decoder = null;
try {
decoder = new Base64Decoder(new BufferedInputStream(new FileInputStream(args[0])));
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = decoder.read(buf)) != -1)
System.out.write(buf, 0, bytesRead);
} finally {
if (decoder != null)
decoder.close();
}
}
}

View file

@ -0,0 +1,112 @@
package com.oreilly.servlet;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
public class Base64Encoder extends FilterOutputStream {
private static final char[] chars = new char[] {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/' };
private int charCount;
private int carryOver;
public Base64Encoder(OutputStream out) {
super(out);
}
public void write(int b) throws IOException {
if (b < 0)
b += 256;
if (this.charCount % 3 == 0) {
int lookup = b >> 2;
this.carryOver = b & 0x3;
this.out.write(chars[lookup]);
} else if (this.charCount % 3 == 1) {
int lookup = (this.carryOver << 4) + (b >> 4) & 0x3F;
this.carryOver = b & 0xF;
this.out.write(chars[lookup]);
} else if (this.charCount % 3 == 2) {
int lookup = (this.carryOver << 2) + (b >> 6) & 0x3F;
this.out.write(chars[lookup]);
lookup = b & 0x3F;
this.out.write(chars[lookup]);
this.carryOver = 0;
}
this.charCount++;
if (this.charCount % 57 == 0)
this.out.write(10);
}
public void write(byte[] buf, int off, int len) throws IOException {
for (int i = 0; i < len; i++)
write(buf[off + i]);
}
public void close() throws IOException {
if (this.charCount % 3 == 1) {
int lookup = this.carryOver << 4 & 0x3F;
this.out.write(chars[lookup]);
this.out.write(61);
this.out.write(61);
} else if (this.charCount % 3 == 2) {
int lookup = this.carryOver << 2 & 0x3F;
this.out.write(chars[lookup]);
this.out.write(61);
}
super.close();
}
public static String encode(String unencoded) {
byte[] bytes = null;
try {
bytes = unencoded.getBytes("8859_1");
} catch (UnsupportedEncodingException ignored) {}
return encode(bytes);
}
public static String encode(byte[] bytes) {
ByteArrayOutputStream out = new ByteArrayOutputStream((int)((double)bytes.length * 1.37D));
Base64Encoder encodedOut = new Base64Encoder(out);
try {
encodedOut.write(bytes);
encodedOut.close();
return out.toString("8859_1");
} catch (IOException ignored) {
return null;
}
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: java com.oreilly.servlet.Base64Encoder fileToEncode");
return;
}
Base64Encoder encoder = null;
BufferedInputStream in = null;
try {
encoder = new Base64Encoder(System.out);
in = new BufferedInputStream(new FileInputStream(args[0]));
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buf)) != -1)
encoder.write(buf, 0, bytesRead);
} finally {
if (in != null)
in.close();
if (encoder != null)
encoder.close();
}
}
}

View file

@ -0,0 +1,64 @@
package com.oreilly.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class CacheHttpServlet extends HttpServlet {
CacheHttpServletResponse cacheResponse;
long cacheLastMod = -1L;
String cacheQueryString = null;
String cachePathInfo = null;
String cacheServletPath = null;
Object lock = new Object();
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
String method = req.getMethod();
if (!method.equals("GET")) {
super.service(req, res);
return;
}
long servletLastMod = getLastModified(req);
if (servletLastMod == -1L) {
super.service(req, res);
return;
}
if (servletLastMod / 1000L * 1000L <= req.getDateHeader("If-Modified-Since")) {
res.setStatus(304);
return;
}
CacheHttpServletResponse localResponseCopy = null;
synchronized (this.lock) {
if (servletLastMod <= this.cacheLastMod && this.cacheResponse.isValid() && equal(this.cacheQueryString, req.getQueryString()) && equal(this.cachePathInfo, req.getPathInfo()) && equal(this.cacheServletPath, req.getServletPath()))
localResponseCopy = this.cacheResponse;
}
if (localResponseCopy != null) {
localResponseCopy.writeTo(res);
return;
}
localResponseCopy = new CacheHttpServletResponse(res);
super.service(req, localResponseCopy);
synchronized (this.lock) {
this.cacheResponse = localResponseCopy;
this.cacheLastMod = servletLastMod;
this.cacheQueryString = req.getQueryString();
this.cachePathInfo = req.getPathInfo();
this.cacheServletPath = req.getServletPath();
}
}
private boolean equal(String s1, String s2) {
if (s1 == null && s2 == null)
return true;
if (s1 == null || s2 == null)
return false;
return s1.equals(s2);
}
}

View file

@ -0,0 +1,263 @@
package com.oreilly.servlet;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Vector;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
class CacheHttpServletResponse implements HttpServletResponse {
private int status;
private Hashtable headers;
private int contentLength;
private String contentType;
private Locale locale;
private Vector cookies;
private boolean didError;
private boolean didRedirect;
private boolean gotStream;
private boolean gotWriter;
private HttpServletResponse delegate;
private CacheServletOutputStream out;
private PrintWriter writer;
CacheHttpServletResponse(HttpServletResponse res) {
this.delegate = res;
try {
this.out = new CacheServletOutputStream(res.getOutputStream());
} catch (IOException e) {
System.out.println("Got IOException constructing cached response: " + e.getMessage());
}
internalReset();
}
private void internalReset() {
this.status = 200;
this.headers = new Hashtable();
this.contentLength = -1;
this.contentType = null;
this.locale = null;
this.cookies = new Vector();
this.didError = false;
this.didRedirect = false;
this.gotStream = false;
this.gotWriter = false;
this.out.getBuffer().reset();
}
public boolean isValid() {
return (this.didError != true && this.didRedirect != true);
}
private void internalSetHeader(String name, Object value) {
Vector v = new Vector();
v.addElement(value);
this.headers.put(name, v);
}
private void internalAddHeader(String name, Object value) {
Vector v = (Vector)this.headers.get(name);
if (v == null)
v = new Vector();
v.addElement(value);
this.headers.put(name, v);
}
public void writeTo(HttpServletResponse res) {
res.setStatus(this.status);
if (this.contentType != null)
res.setContentType(this.contentType);
if (this.locale != null)
res.setLocale(this.locale);
Enumeration enum = this.cookies.elements();
while (enum.hasMoreElements()) {
Cookie c = (Cookie)enum.nextElement();
res.addCookie(c);
}
enum = this.headers.keys();
while (enum.hasMoreElements()) {
String name = (String)enum.nextElement();
Vector values = (Vector)this.headers.get(name);
Enumeration enum2 = values.elements();
while (enum2.hasMoreElements()) {
Object value = enum2.nextElement();
if (value instanceof String)
res.setHeader(name, (String)value);
if (value instanceof Integer)
res.setIntHeader(name, ((Integer)value).intValue());
if (value instanceof Long)
res.setDateHeader(name, ((Long)value).longValue());
}
}
res.setContentLength(this.out.getBuffer().size());
try {
this.out.getBuffer().writeTo((OutputStream)res.getOutputStream());
} catch (IOException e) {
System.out.println("Got IOException writing cached response: " + e.getMessage());
}
}
public ServletOutputStream getOutputStream() throws IOException {
if (this.gotWriter)
throw new IllegalStateException("Cannot get output stream after getting writer");
this.gotStream = true;
return this.out;
}
public PrintWriter getWriter() throws UnsupportedEncodingException {
if (this.gotStream)
throw new IllegalStateException("Cannot get writer after getting output stream");
this.gotWriter = true;
if (this.writer == null) {
OutputStreamWriter w = new OutputStreamWriter((OutputStream)this.out, getCharacterEncoding());
this.writer = new PrintWriter((Writer)w, true);
}
return this.writer;
}
public void setContentLength(int len) {
this.delegate.setContentLength(len);
}
public void setContentType(String type) {
this.delegate.setContentType(type);
this.contentType = type;
}
public String getCharacterEncoding() {
return this.delegate.getCharacterEncoding();
}
public void setBufferSize(int size) throws IllegalStateException {
this.delegate.setBufferSize(size);
}
public int getBufferSize() {
return this.delegate.getBufferSize();
}
public void reset() throws IllegalStateException {
this.delegate.reset();
internalReset();
}
public void resetBuffer() throws IllegalStateException {
this.delegate.resetBuffer();
this.contentLength = -1;
this.out.getBuffer().reset();
}
public boolean isCommitted() {
return this.delegate.isCommitted();
}
public void flushBuffer() throws IOException {
this.delegate.flushBuffer();
}
public void setLocale(Locale loc) {
this.delegate.setLocale(loc);
this.locale = loc;
}
public Locale getLocale() {
return this.delegate.getLocale();
}
public void addCookie(Cookie cookie) {
this.delegate.addCookie(cookie);
this.cookies.addElement(cookie);
}
public boolean containsHeader(String name) {
return this.delegate.containsHeader(name);
}
public void setStatus(int sc, String sm) {
this.delegate.setStatus(sc, sm);
this.status = sc;
}
public void setStatus(int sc) {
this.delegate.setStatus(sc);
this.status = sc;
}
public void setHeader(String name, String value) {
this.delegate.setHeader(name, value);
internalSetHeader(name, value);
}
public void setIntHeader(String name, int value) {
this.delegate.setIntHeader(name, value);
internalSetHeader(name, new Integer(value));
}
public void setDateHeader(String name, long date) {
this.delegate.setDateHeader(name, date);
internalSetHeader(name, new Long(date));
}
public void sendError(int sc, String msg) throws IOException {
this.delegate.sendError(sc, msg);
this.didError = true;
}
public void sendError(int sc) throws IOException {
this.delegate.sendError(sc);
this.didError = true;
}
public void sendRedirect(String location) throws IOException {
this.delegate.sendRedirect(location);
this.didRedirect = true;
}
public String encodeURL(String url) {
return this.delegate.encodeURL(url);
}
public String encodeRedirectURL(String url) {
return this.delegate.encodeRedirectURL(url);
}
public void addHeader(String name, String value) {
internalAddHeader(name, value);
}
public void addIntHeader(String name, int value) {
internalAddHeader(name, new Integer(value));
}
public void addDateHeader(String name, long value) {
internalAddHeader(name, new Long(value));
}
public String encodeUrl(String url) {
return encodeURL(url);
}
public String encodeRedirectUrl(String url) {
return encodeRedirectURL(url);
}
}

View file

@ -0,0 +1,35 @@
package com.oreilly.servlet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
class CacheServletOutputStream extends ServletOutputStream {
ServletOutputStream delegate;
ByteArrayOutputStream cache;
CacheServletOutputStream(ServletOutputStream out) {
this.delegate = out;
this.cache = new ByteArrayOutputStream(4096);
}
public ByteArrayOutputStream getBuffer() {
return this.cache;
}
public void write(int b) throws IOException {
this.delegate.write(b);
this.cache.write(b);
}
public void write(byte[] b) throws IOException {
this.delegate.write(b);
this.cache.write(b);
}
public void write(byte[] buf, int offset, int len) throws IOException {
this.delegate.write(buf, offset, len);
this.cache.write(buf, offset, len);
}
}

View file

@ -0,0 +1,9 @@
package com.oreilly.servlet;
public class CookieNotFoundException extends Exception {
public CookieNotFoundException() {}
public CookieNotFoundException(String s) {
super(s);
}
}

View file

@ -0,0 +1,140 @@
package com.oreilly.servlet;
import java.util.Hashtable;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
public class CookieParser {
private HttpServletRequest req;
private Hashtable cookieJar = new Hashtable();
public CookieParser(HttpServletRequest req) {
this.req = req;
parseCookies();
}
void parseCookies() {
Cookie[] cookies = this.req.getCookies();
if (cookies != null)
for (int i = 0; i < cookies.length; i++) {
String name = cookies[i].getName();
String value = cookies[i].getValue();
this.cookieJar.put(name, value);
}
}
public String getStringCookie(String name) throws CookieNotFoundException {
String value = (String)this.cookieJar.get(name);
if (value == null)
throw new CookieNotFoundException(name + " not found");
return value;
}
public String getStringCookie(String name, String def) {
try {
return getStringCookie(name);
} catch (Exception e) {
return def;
}
}
public boolean getBooleanCookie(String name) throws CookieNotFoundException {
return new Boolean(getStringCookie(name)).booleanValue();
}
public boolean getBooleanCookie(String name, boolean def) {
try {
return getBooleanCookie(name);
} catch (Exception e) {
return def;
}
}
public byte getByteCookie(String name) throws CookieNotFoundException, NumberFormatException {
return Byte.parseByte(getStringCookie(name));
}
public byte getByteCookie(String name, byte def) {
try {
return getByteCookie(name);
} catch (Exception e) {
return def;
}
}
public char getCharCookie(String name) throws CookieNotFoundException {
String param = getStringCookie(name);
if (param.length() == 0)
throw new CookieNotFoundException(name + " is empty string");
return param.charAt(0);
}
public char getCharCookie(String name, char def) {
try {
return getCharCookie(name);
} catch (Exception e) {
return def;
}
}
public double getDoubleCookie(String name) throws CookieNotFoundException, NumberFormatException {
return new Double(getStringCookie(name)).doubleValue();
}
public double getDoubleCookie(String name, double def) {
try {
return getDoubleCookie(name);
} catch (Exception e) {
return def;
}
}
public float getFloatCookie(String name) throws CookieNotFoundException, NumberFormatException {
return new Float(getStringCookie(name)).floatValue();
}
public float getFloatCookie(String name, float def) {
try {
return getFloatCookie(name);
} catch (Exception e) {
return def;
}
}
public int getIntCookie(String name) throws CookieNotFoundException, NumberFormatException {
return Integer.parseInt(getStringCookie(name));
}
public int getIntCookie(String name, int def) {
try {
return getIntCookie(name);
} catch (Exception e) {
return def;
}
}
public long getLongCookie(String name) throws CookieNotFoundException, NumberFormatException {
return Long.parseLong(getStringCookie(name));
}
public long getLongCookie(String name, long def) {
try {
return getLongCookie(name);
} catch (Exception e) {
return def;
}
}
public short getShortCookie(String name) throws CookieNotFoundException, NumberFormatException {
return Short.parseShort(getStringCookie(name));
}
public short getShortCookie(String name, short def) {
try {
return getShortCookie(name);
} catch (Exception e) {
return def;
}
}
}

View file

@ -0,0 +1,39 @@
package com.oreilly.servlet;
import java.io.IOException;
import java.net.ServerSocket;
class Daemon extends Thread {
private ServerSocket serverSocket;
private DaemonHttpServlet servlet;
public Daemon(DaemonHttpServlet servlet) {
this.servlet = servlet;
}
public void run() {
try {
this.serverSocket = new ServerSocket(this.servlet.getSocketPort());
} catch (Exception e) {
this.servlet.log("Problem establishing server socket: " + e.getClass().getName() + ": " + e.getMessage());
return;
}
try {
while (true) {
try {
this.servlet.handleClient(this.serverSocket.accept());
} catch (IOException ioe) {
this.servlet.log("Problem accepting client's socket connection: " + ioe.getClass().getName() + ": " + ioe.getMessage());
}
}
} catch (ThreadDeath e) {
try {
this.serverSocket.close();
} catch (IOException ioe) {
this.servlet.log("Problem closing server socket: " + ioe.getClass().getName() + ": " + ioe.getMessage());
}
return;
}
}
}

View file

@ -0,0 +1,41 @@
package com.oreilly.servlet;
import java.net.Socket;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public abstract class DaemonHttpServlet extends HttpServlet {
protected int DEFAULT_PORT = 1313;
private Thread daemonThread;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
this.daemonThread = new Daemon(this);
this.daemonThread.start();
} catch (Exception e) {
log("Problem starting socket server daemon thread" + e.getClass().getName() + ": " + e.getMessage());
}
}
protected int getSocketPort() {
try {
return Integer.parseInt(getInitParameter("socketPort"));
} catch (NumberFormatException e) {
return this.DEFAULT_PORT;
}
}
public abstract void handleClient(Socket paramSocket);
public void destroy() {
try {
this.daemonThread.stop();
this.daemonThread = null;
} catch (Exception e) {
log("Problem stopping server socket daemon thread: " + e.getClass().getName() + ": " + e.getMessage());
}
}
}

View file

@ -0,0 +1,119 @@
package com.oreilly.servlet;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
public class HttpMessage {
URL servlet = null;
Hashtable headers = null;
public HttpMessage(URL servlet) {
this.servlet = servlet;
}
public InputStream sendGetMessage() throws IOException {
return sendGetMessage(null);
}
public InputStream sendGetMessage(Properties args) throws IOException {
String argString = "";
if (args != null)
argString = "?" + toEncodedString(args);
URL url = new URL(this.servlet.toExternalForm() + argString);
URLConnection con = url.openConnection();
con.setUseCaches(false);
sendHeaders(con);
return con.getInputStream();
}
public InputStream sendPostMessage() throws IOException {
return sendPostMessage((Properties)null);
}
public InputStream sendPostMessage(Properties args) throws IOException {
String argString = "";
if (args != null)
argString = toEncodedString(args);
URLConnection con = this.servlet.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
sendHeaders(con);
DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes(argString);
out.flush();
out.close();
return con.getInputStream();
}
public InputStream sendPostMessage(Serializable obj) throws IOException {
URLConnection con = this.servlet.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/x-java-serialized-object");
sendHeaders(con);
ObjectOutputStream out = new ObjectOutputStream(con.getOutputStream());
out.writeObject(obj);
out.flush();
out.close();
return con.getInputStream();
}
public void setHeader(String name, String value) {
if (this.headers == null)
this.headers = new Hashtable();
this.headers.put(name, value);
}
private void sendHeaders(URLConnection con) {
if (this.headers != null) {
Enumeration enum = this.headers.keys();
while (enum.hasMoreElements()) {
String name = (String)enum.nextElement();
String value = (String)this.headers.get(name);
con.setRequestProperty(name, value);
}
}
}
public void setCookie(String name, String value) {
if (this.headers == null)
this.headers = new Hashtable();
String existingCookies = (String)this.headers.get("Cookie");
if (existingCookies == null) {
setHeader("Cookie", name + "=" + value);
} else {
setHeader("Cookie", existingCookies + "; " + name + "=" + value);
}
}
public void setAuthorization(String name, String password) {
String authorization = Base64Encoder.encode(name + ":" + password);
setHeader("Authorization", "Basic " + authorization);
}
private String toEncodedString(Properties args) {
StringBuffer buf = new StringBuffer();
Enumeration names = args.propertyNames();
while (names.hasMoreElements()) {
String name = (String)names.nextElement();
String value = args.getProperty(name);
buf.append(URLEncoder.encode(name) + "=" + URLEncoder.encode(value));
if (names.hasMoreElements())
buf.append("&");
}
return buf.toString();
}
}

View file

@ -0,0 +1,41 @@
package com.oreilly.servlet;
import java.net.URL;
import java.net.URLStreamHandlerFactory;
import java.security.Provider;
import java.security.Security;
public class HttpsMessage extends HttpMessage {
static boolean m_bStreamHandlerSet = false;
public HttpsMessage(String szURL) throws Exception {
super(null);
if (!m_bStreamHandlerSet) {
String szVendor = System.getProperty("java.vendor");
String szVersion = System.getProperty("java.version");
Double dVersion = new Double(szVersion.substring(0, 3));
if (-1 < szVendor.indexOf("Microsoft")) {
try {
Class clsFactory = Class.forName("com.ms.net.wininet.WininetStreamHandlerFactory");
if (null != clsFactory)
URL.setURLStreamHandlerFactory((URLStreamHandlerFactory)clsFactory.newInstance());
} catch (ClassNotFoundException cfe) {
throw new Exception("Unable to load the Microsoft SSL stream handler. Check classpath." + cfe.toString());
} catch (Error err) {
m_bStreamHandlerSet = true;
}
} else if (1.2D <= dVersion.doubleValue()) {
System.getProperties().put("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
try {
Class clsFactory = Class.forName("com.sun.net.ssl.internal.ssl.Provider");
if (null != clsFactory && null == Security.getProvider("SunJSSE"))
Security.addProvider((Provider)clsFactory.newInstance());
} catch (ClassNotFoundException cfe) {
throw new Exception("Unable to load the JSSE SSL stream handler. Check classpath." + cfe.toString());
}
}
m_bStreamHandlerSet = true;
}
this.servlet = new URL(szURL);
}
}

View file

@ -0,0 +1,93 @@
package com.oreilly.servlet;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
public class LocaleNegotiator {
private ResourceBundle chosenBundle;
private Locale chosenLocale;
private String chosenCharset;
public LocaleNegotiator(String bundleName, String languages, String charsets) {
Locale defaultLocale = new Locale("en", "US");
String defaultCharset = "ISO-8859-1";
ResourceBundle defaultBundle = null;
try {
defaultBundle = ResourceBundle.getBundle(bundleName, defaultLocale);
} catch (MissingResourceException e) {}
if (languages == null) {
this.chosenLocale = defaultLocale;
this.chosenCharset = defaultCharset;
this.chosenBundle = defaultBundle;
return;
}
StringTokenizer tokenizer = new StringTokenizer(languages, ",");
while (tokenizer.hasMoreTokens()) {
String lang = tokenizer.nextToken();
Locale loc = getLocaleForLanguage(lang);
ResourceBundle bundle = getBundleNoFallback(bundleName, loc);
if (bundle == null)
continue;
String charset = getCharsetForLocale(loc, charsets);
if (charset == null)
continue;
this.chosenLocale = loc;
this.chosenBundle = bundle;
this.chosenCharset = charset;
return;
}
this.chosenLocale = defaultLocale;
this.chosenCharset = defaultCharset;
this.chosenBundle = defaultBundle;
}
public ResourceBundle getBundle() {
return this.chosenBundle;
}
public Locale getLocale() {
return this.chosenLocale;
}
public String getCharset() {
return this.chosenCharset;
}
private Locale getLocaleForLanguage(String lang) {
Locale locale;
int semi;
if ((semi = lang.indexOf(';')) != -1)
lang = lang.substring(0, semi);
lang = lang.trim();
int dash;
if ((dash = lang.indexOf('-')) == -1) {
locale = new Locale(lang, "");
} else {
locale = new Locale(lang.substring(0, dash), lang.substring(dash + 1));
}
return locale;
}
private ResourceBundle getBundleNoFallback(String bundleName, Locale loc) {
ResourceBundle fallback = null;
try {
fallback = ResourceBundle.getBundle(bundleName, new Locale("bogus", ""));
} catch (MissingResourceException e) {}
try {
ResourceBundle bundle = ResourceBundle.getBundle(bundleName, loc);
if (bundle != fallback)
return bundle;
if (bundle == fallback && loc.getLanguage().equals(Locale.getDefault().getLanguage()))
return bundle;
} catch (MissingResourceException e) {}
return null;
}
protected String getCharsetForLocale(Locale loc, String charsets) {
return LocaleToCharsetMap.getCharset(loc);
}
}

View file

@ -0,0 +1,58 @@
package com.oreilly.servlet;
import java.util.Hashtable;
import java.util.Locale;
public class LocaleToCharsetMap {
private static Hashtable map = new Hashtable();
static {
map.put("ar", "ISO-8859-6");
map.put("be", "ISO-8859-5");
map.put("bg", "ISO-8859-5");
map.put("ca", "ISO-8859-1");
map.put("cs", "ISO-8859-2");
map.put("da", "ISO-8859-1");
map.put("de", "ISO-8859-1");
map.put("el", "ISO-8859-7");
map.put("en", "ISO-8859-1");
map.put("es", "ISO-8859-1");
map.put("et", "ISO-8859-1");
map.put("fi", "ISO-8859-1");
map.put("fr", "ISO-8859-1");
map.put("hr", "ISO-8859-2");
map.put("hu", "ISO-8859-2");
map.put("is", "ISO-8859-1");
map.put("it", "ISO-8859-1");
map.put("iw", "ISO-8859-8");
map.put("ja", "Shift_JIS");
map.put("ko", "EUC-KR");
map.put("lt", "ISO-8859-2");
map.put("lv", "ISO-8859-2");
map.put("mk", "ISO-8859-5");
map.put("nl", "ISO-8859-1");
map.put("no", "ISO-8859-1");
map.put("pl", "ISO-8859-2");
map.put("pt", "ISO-8859-1");
map.put("ro", "ISO-8859-2");
map.put("ru", "ISO-8859-5");
map.put("sh", "ISO-8859-5");
map.put("sk", "ISO-8859-2");
map.put("sl", "ISO-8859-2");
map.put("sq", "ISO-8859-2");
map.put("sr", "ISO-8859-5");
map.put("sv", "ISO-8859-1");
map.put("tr", "ISO-8859-9");
map.put("uk", "ISO-8859-5");
map.put("zh", "GB2312");
map.put("zh_TW", "Big5");
}
public static String getCharset(Locale loc) {
String charset = (String)map.get(loc.toString());
if (charset != null)
return charset;
charset = (String)map.get(loc.getLanguage());
return charset;
}
}

View file

@ -0,0 +1,215 @@
package com.oreilly.servlet;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
public class MailMessage {
String host;
String from;
Vector to;
Vector cc;
Hashtable headers;
MailPrintStream out;
BufferedReader in;
Socket socket;
public MailMessage() throws IOException {
this("localhost");
}
public MailMessage(String host) throws IOException {
this.host = host;
this.to = new Vector();
this.cc = new Vector();
this.headers = new Hashtable();
setHeader("X-Mailer", "com.oreilly.servlet.MailMessage (www.servlets.com)");
connect();
sendHelo();
}
public void from(String from) throws IOException {
sendFrom(from);
this.from = from;
}
public void to(String to) throws IOException {
sendRcpt(to);
this.to.addElement(to);
}
public void cc(String cc) throws IOException {
sendRcpt(cc);
this.cc.addElement(cc);
}
public void bcc(String bcc) throws IOException {
sendRcpt(bcc);
}
public void setSubject(String subj) {
this.headers.put("Subject", subj);
}
public void setHeader(String name, String value) {
this.headers.put(name, value);
}
public PrintStream getPrintStream() throws IOException {
setFromHeader();
setToHeader();
setCcHeader();
sendData();
flushHeaders();
return this.out;
}
void setFromHeader() {
setHeader("From", this.from);
}
void setToHeader() {
setHeader("To", vectorToList(this.to));
}
void setCcHeader() {
if (!this.cc.isEmpty())
setHeader("Cc", vectorToList(this.cc));
}
String vectorToList(Vector v) {
StringBuffer buf = new StringBuffer();
Enumeration e = v.elements();
while (e.hasMoreElements()) {
buf.append(e.nextElement());
if (e.hasMoreElements())
buf.append(", ");
}
return buf.toString();
}
void flushHeaders() throws IOException {
Enumeration e = this.headers.keys();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = (String)this.headers.get(name);
this.out.println(name + ": " + value);
}
this.out.println();
this.out.flush();
}
public void sendAndClose() throws IOException {
sendDot();
disconnect();
}
static String sanitizeAddress(String s) {
int paramDepth = 0;
int start = 0;
int end = 0;
int len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if (c == '(') {
paramDepth++;
if (start == 0)
end = i;
} else if (c == ')') {
paramDepth--;
if (end == 0)
start = i + 1;
} else if (paramDepth == 0 && c == '<') {
start = i + 1;
} else if (paramDepth == 0 && c == '>') {
end = i;
}
}
if (end == 0)
end = len;
return s.substring(start, end);
}
void connect() throws IOException {
this.socket = new Socket(this.host, 25);
this.out = new MailPrintStream(new BufferedOutputStream(this.socket.getOutputStream()));
this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
getReady();
}
void getReady() throws IOException {
String response = this.in.readLine();
int[] ok = { 220 };
if (!isResponseOK(response, ok))
throw new IOException("Didn't get introduction from server: " + response);
}
void sendHelo() throws IOException {
String local = InetAddress.getLocalHost().getHostName();
int[] ok = { 250 };
send("HELO " + local, ok);
}
void sendFrom(String from) throws IOException {
int[] ok = { 250 };
send("MAIL FROM: <" + sanitizeAddress(from) + ">", ok);
}
void sendRcpt(String rcpt) throws IOException {
int[] ok = { 250, 251 };
send("RCPT TO: <" + sanitizeAddress(rcpt) + ">", ok);
}
void sendData() throws IOException {
int[] ok = { 354 };
send("DATA", ok);
}
void sendDot() throws IOException {
int[] ok = { 250 };
send("\r\n.", ok);
}
void sendQuit() throws IOException {
int[] ok = { 221 };
send("QUIT", ok);
}
void send(String msg, int[] ok) throws IOException {
this.out.rawPrint(msg + "\r\n");
String response = this.in.readLine();
if (!isResponseOK(response, ok))
throw new IOException("Unexpected reply to command: " + msg + ": " + response);
}
boolean isResponseOK(String response, int[] ok) {
for (int i = 0; i < ok.length; i++) {
if (response.startsWith("" + ok[i]))
return true;
}
return false;
}
void disconnect() throws IOException {
if (this.out != null)
this.out.close();
if (this.in != null)
this.in.close();
if (this.socket != null)
this.socket.close();
}
}

View file

@ -0,0 +1,45 @@
package com.oreilly.servlet;
import java.io.OutputStream;
import java.io.PrintStream;
class MailPrintStream extends PrintStream {
int lastChar;
public MailPrintStream(OutputStream out) {
super(out, true);
}
public void write(int b) {
if (b == 10 && this.lastChar != 13) {
rawWrite(13);
rawWrite(b);
} else if (b == 46 && this.lastChar == 10) {
rawWrite(46);
rawWrite(b);
} else if (b != 10 && this.lastChar == 13) {
rawWrite(10);
rawWrite(b);
if (b == 46)
rawWrite(46);
} else {
rawWrite(b);
}
this.lastChar = b;
}
public void write(byte[] buf, int off, int len) {
for (int i = 0; i < len; i++)
write(buf[off + i]);
}
void rawWrite(int b) {
super.write(b);
}
void rawPrint(String s) {
int len = s.length();
for (int i = 0; i < len; i++)
rawWrite(s.charAt(i));
}
}

View file

@ -0,0 +1,45 @@
package com.oreilly.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class MultipartFilter implements Filter {
private FilterConfig config = null;
private String dir = null;
public void init(FilterConfig config) throws ServletException {
this.config = config;
this.dir = config.getInitParameter("uploadDir");
if (this.dir == null) {
File tempdir = (File)config.getServletContext().getAttribute("javax.servlet.context.tempdir");
if (tempdir != null) {
this.dir = tempdir.toString();
} else {
throw new ServletException("MultipartFilter: No upload directory found: set an uploadDir init parameter or ensure the javax.servlet.context.tempdir directory is valid");
}
}
}
public void destroy() {
this.config = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
String type = req.getHeader("Content-Type");
if (type == null || !type.startsWith("multipart/form-data")) {
chain.doFilter(request, response);
} else {
MultipartWrapper multi = new MultipartWrapper(req, this.dir);
chain.doFilter((ServletRequest)multi, response);
}
}
}

View file

@ -0,0 +1,173 @@
package com.oreilly.servlet;
import com.oreilly.servlet.multipart.FilePart;
import com.oreilly.servlet.multipart.FileRenamePolicy;
import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.ParamPart;
import com.oreilly.servlet.multipart.Part;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpUtils;
public class MultipartRequest {
private static final int DEFAULT_MAX_POST_SIZE = 1048576;
protected Hashtable parameters = new Hashtable();
protected Hashtable files = new Hashtable();
public MultipartRequest(HttpServletRequest request, String saveDirectory) throws IOException {
this(request, saveDirectory, 1048576);
}
public MultipartRequest(HttpServletRequest request, String saveDirectory, int maxPostSize) throws IOException {
this(request, saveDirectory, maxPostSize, null, null);
}
public MultipartRequest(HttpServletRequest request, String saveDirectory, String encoding) throws IOException {
this(request, saveDirectory, 1048576, encoding, null);
}
public MultipartRequest(HttpServletRequest request, String saveDirectory, int maxPostSize, FileRenamePolicy policy) throws IOException {
this(request, saveDirectory, maxPostSize, null, policy);
}
public MultipartRequest(HttpServletRequest request, String saveDirectory, int maxPostSize, String encoding) throws IOException {
this(request, saveDirectory, maxPostSize, encoding, null);
}
public MultipartRequest(HttpServletRequest request, String saveDirectory, int maxPostSize, String encoding, FileRenamePolicy policy) throws IOException {
if (request == null)
throw new IllegalArgumentException("request cannot be null");
if (saveDirectory == null)
throw new IllegalArgumentException("saveDirectory cannot be null");
if (maxPostSize <= 0)
throw new IllegalArgumentException("maxPostSize must be positive");
File dir = new File(saveDirectory);
if (!dir.isDirectory())
throw new IllegalArgumentException("Not a directory: " + saveDirectory);
if (!dir.canWrite())
throw new IllegalArgumentException("Not writable: " + saveDirectory);
MultipartParser parser = new MultipartParser(request, maxPostSize, true, true, encoding);
if (request.getQueryString() != null) {
Hashtable queryParameters = HttpUtils.parseQueryString(request.getQueryString());
Enumeration queryParameterNames = queryParameters.keys();
while (queryParameterNames.hasMoreElements()) {
Object paramName = queryParameterNames.nextElement();
String[] values = (String[])queryParameters.get(paramName);
Vector newValues = new Vector();
for (int i = 0; i < values.length; i++)
newValues.add(values[i]);
this.parameters.put(paramName, newValues);
}
}
Part part;
while ((part = parser.readNextPart()) != null) {
String name = part.getName();
if (part.isParam()) {
ParamPart paramPart = (ParamPart)part;
String value = paramPart.getStringValue();
Vector existingValues = (Vector)this.parameters.get(name);
if (existingValues == null) {
existingValues = new Vector();
this.parameters.put(name, existingValues);
}
existingValues.addElement(value);
continue;
}
if (part.isFile()) {
FilePart filePart = (FilePart)part;
String fileName = filePart.getFileName();
if (fileName != null) {
filePart.setRenamePolicy(policy);
filePart.writeTo(dir);
this.files.put(name, new UploadedFile(dir.toString(), filePart.getFileName(), fileName, filePart.getContentType()));
continue;
}
this.files.put(name, new UploadedFile(null, null, null, null));
}
}
}
public MultipartRequest(ServletRequest request, String saveDirectory) throws IOException {
this((HttpServletRequest)request, saveDirectory);
}
public MultipartRequest(ServletRequest request, String saveDirectory, int maxPostSize) throws IOException {
this((HttpServletRequest)request, saveDirectory, maxPostSize);
}
public Enumeration getParameterNames() {
return this.parameters.keys();
}
public Enumeration getFileNames() {
return this.files.keys();
}
public String getParameter(String name) {
try {
Vector values = (Vector)this.parameters.get(name);
if (values == null || values.size() == 0)
return null;
String value = (String)values.elementAt(values.size() - 1);
return value;
} catch (Exception e) {
return null;
}
}
public String[] getParameterValues(String name) {
try {
Vector values = (Vector)this.parameters.get(name);
if (values == null || values.size() == 0)
return null;
String[] valuesArray = new String[values.size()];
values.copyInto(valuesArray);
return valuesArray;
} catch (Exception e) {
return null;
}
}
public String getFilesystemName(String name) {
try {
UploadedFile file = (UploadedFile)this.files.get(name);
return file.getFilesystemName();
} catch (Exception e) {
return null;
}
}
public String getOriginalFileName(String name) {
try {
UploadedFile file = (UploadedFile)this.files.get(name);
return file.getOriginalFileName();
} catch (Exception e) {
return null;
}
}
public String getContentType(String name) {
try {
UploadedFile file = (UploadedFile)this.files.get(name);
return file.getContentType();
} catch (Exception e) {
return null;
}
}
public File getFile(String name) {
try {
UploadedFile file = (UploadedFile)this.files.get(name);
return file.getFile();
} catch (Exception e) {
return null;
}
}
}

View file

@ -0,0 +1,41 @@
package com.oreilly.servlet;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
public class MultipartResponse {
HttpServletResponse res;
ServletOutputStream out;
boolean endedLastResponse = true;
public MultipartResponse(HttpServletResponse response) throws IOException {
this.res = response;
this.out = this.res.getOutputStream();
this.res.setContentType("multipart/x-mixed-replace;boundary=End");
this.out.println();
this.out.println("--End");
}
public void startResponse(String contentType) throws IOException {
if (!this.endedLastResponse)
endResponse();
this.out.println("Content-type: " + contentType);
this.out.println();
this.endedLastResponse = false;
}
public void endResponse() throws IOException {
this.out.println();
this.out.println("--End");
this.out.flush();
this.endedLastResponse = true;
}
public void finish() throws IOException {
this.out.println("--End--");
this.out.flush();
}
}

View file

@ -0,0 +1,56 @@
package com.oreilly.servlet;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class MultipartWrapper extends HttpServletRequestWrapper {
MultipartRequest mreq = null;
public MultipartWrapper(HttpServletRequest req, String dir) throws IOException {
super(req);
this.mreq = new MultipartRequest(req, dir);
}
public Enumeration getParameterNames() {
return this.mreq.getParameterNames();
}
public String getParameter(String name) {
return this.mreq.getParameter(name);
}
public String[] getParameterValues(String name) {
return this.mreq.getParameterValues(name);
}
public Map getParameterMap() {
Map map = new HashMap();
Enumeration enum = getParameterNames();
while (enum.hasMoreElements()) {
String name = (String)enum.nextElement();
map.put(name, this.mreq.getParameterValues(name));
}
return map;
}
public Enumeration getFileNames() {
return this.mreq.getFileNames();
}
public String getFilesystemName(String name) {
return this.mreq.getFilesystemName(name);
}
public String getContentType(String name) {
return this.mreq.getContentType(name);
}
public File getFile(String name) {
return this.mreq.getFile(name);
}
}

View file

@ -0,0 +1,9 @@
package com.oreilly.servlet;
public class ParameterNotFoundException extends Exception {
public ParameterNotFoundException() {}
public ParameterNotFoundException(String s) {
super(s);
}
}

View file

@ -0,0 +1,161 @@
package com.oreilly.servlet;
import java.io.UnsupportedEncodingException;
import java.util.Vector;
import javax.servlet.ServletRequest;
public class ParameterParser {
private ServletRequest req;
private String encoding;
public ParameterParser(ServletRequest req) {
this.req = req;
}
public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException {
new String("".getBytes("8859_1"), encoding);
this.encoding = encoding;
}
public String getStringParameter(String name) throws ParameterNotFoundException {
String[] values = this.req.getParameterValues(name);
if (values == null)
throw new ParameterNotFoundException(name + " not found");
if (values[0].length() == 0)
throw new ParameterNotFoundException(name + " was empty");
if (this.encoding == null)
return values[0];
try {
return new String(values[0].getBytes("8859_1"), this.encoding);
} catch (UnsupportedEncodingException e) {
return values[0];
}
}
public String getStringParameter(String name, String def) {
try {
return getStringParameter(name);
} catch (Exception e) {
return def;
}
}
public boolean getBooleanParameter(String name) throws ParameterNotFoundException, NumberFormatException {
String value = getStringParameter(name).toLowerCase();
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("on") || value.equalsIgnoreCase("yes"))
return true;
if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("off") || value.equalsIgnoreCase("no"))
return false;
throw new NumberFormatException("Parameter " + name + " value " + value + " is not a boolean");
}
public boolean getBooleanParameter(String name, boolean def) {
try {
return getBooleanParameter(name);
} catch (Exception e) {
return def;
}
}
public byte getByteParameter(String name) throws ParameterNotFoundException, NumberFormatException {
return Byte.parseByte(getStringParameter(name));
}
public byte getByteParameter(String name, byte def) {
try {
return getByteParameter(name);
} catch (Exception e) {
return def;
}
}
public char getCharParameter(String name) throws ParameterNotFoundException {
String param = getStringParameter(name);
if (param.length() == 0)
throw new ParameterNotFoundException(name + " is empty string");
return param.charAt(0);
}
public char getCharParameter(String name, char def) {
try {
return getCharParameter(name);
} catch (Exception e) {
return def;
}
}
public double getDoubleParameter(String name) throws ParameterNotFoundException, NumberFormatException {
return new Double(getStringParameter(name)).doubleValue();
}
public double getDoubleParameter(String name, double def) {
try {
return getDoubleParameter(name);
} catch (Exception e) {
return def;
}
}
public float getFloatParameter(String name) throws ParameterNotFoundException, NumberFormatException {
return new Float(getStringParameter(name)).floatValue();
}
public float getFloatParameter(String name, float def) {
try {
return getFloatParameter(name);
} catch (Exception e) {
return def;
}
}
public int getIntParameter(String name) throws ParameterNotFoundException, NumberFormatException {
return Integer.parseInt(getStringParameter(name));
}
public int getIntParameter(String name, int def) {
try {
return getIntParameter(name);
} catch (Exception e) {
return def;
}
}
public long getLongParameter(String name) throws ParameterNotFoundException, NumberFormatException {
return Long.parseLong(getStringParameter(name));
}
public long getLongParameter(String name, long def) {
try {
return getLongParameter(name);
} catch (Exception e) {
return def;
}
}
public short getShortParameter(String name) throws ParameterNotFoundException, NumberFormatException {
return Short.parseShort(getStringParameter(name));
}
public short getShortParameter(String name, short def) {
try {
return getShortParameter(name);
} catch (Exception e) {
return def;
}
}
public String[] getMissingParameters(String[] required) {
Vector missing = new Vector();
for (int i = 0; i < required.length; i++) {
String val = getStringParameter(required[i], null);
if (val == null)
missing.addElement(required[i]);
}
if (missing.size() == 0)
return null;
String[] ret = new String[missing.size()];
missing.copyInto(ret);
return ret;
}
}

View file

@ -0,0 +1,74 @@
package com.oreilly.servlet;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
public abstract class RemoteDaemonHttpServlet extends DaemonHttpServlet implements Remote {
protected Registry registry;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
UnicastRemoteObject.exportObject(this);
bind();
} catch (RemoteException e) {
log("Problem binding to RMI registry: " + e.getMessage());
}
}
public void destroy() {
super.destroy();
unbind();
}
protected String getRegistryName() {
String name = getInitParameter("registryName");
if (name != null)
return name;
return getClass().getName();
}
protected int getRegistryPort() {
try {
return Integer.parseInt(getInitParameter("registryPort"));
} catch (NumberFormatException e) {
return 1099;
}
}
protected void bind() {
try {
this.registry = LocateRegistry.getRegistry(getRegistryPort());
this.registry.list();
} catch (Exception e) {
this.registry = null;
}
if (this.registry == null)
try {
this.registry = LocateRegistry.createRegistry(getRegistryPort());
} catch (Exception e) {
log("Could not get or create RMI registry on port " + getRegistryPort() + ": " + e.getMessage());
return;
}
try {
this.registry.rebind(getRegistryName(), this);
} catch (Exception e) {
log("humbug Could not bind to RMI registry: " + e.getMessage());
return;
}
}
protected void unbind() {
try {
if (this.registry != null)
this.registry.unbind(getRegistryName());
} catch (Exception e) {
log("Problem unbinding from RMI registry: " + e.getMessage());
}
}
}

View file

@ -0,0 +1,74 @@
package com.oreilly.servlet;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public abstract class RemoteHttpServlet extends HttpServlet implements Remote {
protected Registry registry;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
UnicastRemoteObject.exportObject(this);
bind();
} catch (RemoteException e) {
log("Problem binding to RMI registry: " + e.getMessage());
}
}
public void destroy() {
unbind();
}
protected String getRegistryName() {
String name = getInitParameter("registryName");
if (name != null)
return name;
return getClass().getName();
}
protected int getRegistryPort() {
try {
return Integer.parseInt(getInitParameter("registryPort"));
} catch (NumberFormatException e) {
return 1099;
}
}
protected void bind() {
try {
this.registry = LocateRegistry.getRegistry(getRegistryPort());
this.registry.list();
} catch (Exception e) {
this.registry = null;
}
if (this.registry == null)
try {
this.registry = LocateRegistry.createRegistry(getRegistryPort());
} catch (Exception e) {
log("Could not get or create RMI registry on port " + getRegistryPort() + ": " + e.getMessage());
return;
}
try {
this.registry.rebind(getRegistryName(), this);
} catch (Exception e) {
log("Could not bind to RMI registry: " + e.getMessage());
return;
}
}
protected void unbind() {
try {
if (this.registry != null)
this.registry.unbind(getRegistryName());
} catch (Exception e) {
log("Problem unbinding from RMI registry: " + e.getMessage());
}
}
}

View file

@ -0,0 +1,118 @@
package com.oreilly.servlet;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
public class ServletUtils {
public static void returnFile(String filename, OutputStream out) throws FileNotFoundException, IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(filename);
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buf)) != -1)
out.write(buf, 0, bytesRead);
} finally {
if (fis != null)
fis.close();
}
}
public static void returnURL(URL url, OutputStream out) throws IOException {
InputStream in = url.openStream();
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buf)) != -1)
out.write(buf, 0, bytesRead);
}
public static void returnURL(URL url, Writer out) throws IOException {
URLConnection con = url.openConnection();
con.connect();
String encoding = con.getContentEncoding();
BufferedReader in = null;
if (encoding == null) {
in = new BufferedReader(new InputStreamReader(url.openStream()));
} else {
in = new BufferedReader(new InputStreamReader(url.openStream(), encoding));
}
char[] buf = new char[4096];
int charsRead;
while ((charsRead = in.read(buf)) != -1)
out.write(buf, 0, charsRead);
}
public static String getStackTraceAsString(Throwable t) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(bytes, true);
t.printStackTrace(writer);
return bytes.toString();
}
public static Servlet getServlet(String name, ServletRequest req, ServletContext context) {
try {
Servlet servlet = context.getServlet(name);
if (servlet != null)
return servlet;
Socket socket = new Socket(req.getServerName(), req.getServerPort());
socket.setSoTimeout(4000);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("GET /servlet/" + name + " HTTP/1.0");
out.println();
try {
socket.getInputStream().read();
} catch (InterruptedIOException e) {}
out.close();
return context.getServlet(name);
} catch (Exception e) {
return null;
}
}
public static String[] split(String str, String delim) {
Vector v = new Vector();
StringTokenizer tokenizer = new StringTokenizer(str, delim);
while (tokenizer.hasMoreTokens())
v.addElement(tokenizer.nextToken());
String[] ret = new String[v.size()];
for (int i = 0; i < ret.length; i++)
ret[i] = (String)v.elementAt(i);
return ret;
}
public static URL getResource(ServletContext context, String resource) throws IOException {
if (resource == null)
throw new FileNotFoundException("Requested resource was null (passed in null)");
if (resource.endsWith("/") || resource.endsWith("\\") || resource.endsWith("."))
throw new MalformedURLException("Path may not end with a slash or dot");
if (resource.indexOf("..") != -1)
throw new MalformedURLException("Path may not contain double dots");
String upperResource = resource.toUpperCase();
if (upperResource.startsWith("/WEB-INF") || upperResource.startsWith("/META-INF"))
throw new MalformedURLException("Path may not begin with /WEB-INF or /META-INF");
if (upperResource.endsWith(".JSP"))
throw new MalformedURLException("Path may not end with .jsp");
URL url = context.getResource(resource);
if (url == null)
throw new FileNotFoundException("Requested resource was null (" + resource + ")");
return url;
}
}

View file

@ -0,0 +1,38 @@
package com.oreilly.servlet;
import java.io.File;
class UploadedFile {
private String dir;
private String filename;
private String original;
private String type;
UploadedFile(String dir, String filename, String original, String type) {
this.dir = dir;
this.filename = filename;
this.original = original;
this.type = type;
}
public String getContentType() {
return this.type;
}
public String getFilesystemName() {
return this.filename;
}
public String getOriginalFileName() {
return this.original;
}
public File getFile() {
if (this.dir == null || this.filename == null)
return null;
return new File(this.dir + File.separator + this.filename);
}
}

View file

@ -0,0 +1,45 @@
package com.oreilly.servlet;
public class VersionDetector {
static String servletVersion;
static String javaVersion;
public static String getServletVersion() {
if (servletVersion != null)
return servletVersion;
String ver = null;
try {
ver = "1.0";
Class.forName("javax.servlet.http.HttpSession");
ver = "2.0";
Class.forName("javax.servlet.RequestDispatcher");
ver = "2.1";
Class.forName("javax.servlet.http.HttpServletResponse").getDeclaredField("SC_EXPECTATION_FAILED");
ver = "2.2";
Class.forName("javax.servlet.Filter");
ver = "2.3";
} catch (Throwable t) {}
servletVersion = ver;
return servletVersion;
}
public static String getJavaVersion() {
if (javaVersion != null)
return javaVersion;
String ver = null;
try {
ver = "1.0";
Class.forName("java.lang.Void");
ver = "1.1";
Class.forName("java.lang.ThreadLocal");
ver = "1.2";
Class.forName("java.lang.StrictMath");
ver = "1.3";
Class.forName("java.net.URI");
ver = "1.4";
} catch (Throwable t) {}
javaVersion = ver;
return javaVersion;
}
}

View file

@ -0,0 +1,100 @@
package com.oreilly.servlet.multipart;
import java.io.IOException;
import javax.servlet.ServletInputStream;
public class BufferedServletInputStream extends ServletInputStream {
private ServletInputStream in;
private byte[] buf = new byte[65536];
private int count;
private int pos;
public BufferedServletInputStream(ServletInputStream in) {
this.in = in;
}
private void fill() throws IOException {
int i = this.in.read(this.buf, 0, this.buf.length);
if (i > 0) {
this.pos = 0;
this.count = i;
}
}
public int readLine(byte[] b, int off, int len) throws IOException {
int total = 0;
if (len == 0)
return 0;
int avail = this.count - this.pos;
if (avail <= 0) {
fill();
avail = this.count - this.pos;
if (avail <= 0)
return -1;
}
int copy = Math.min(len, avail);
int eol = findeol(this.buf, this.pos, copy);
if (eol != -1)
copy = eol;
System.arraycopy(this.buf, this.pos, b, off, copy);
this.pos += copy;
total += copy;
while (total < len && eol == -1) {
fill();
avail = this.count - this.pos;
if (avail <= 0)
return total;
copy = Math.min(len - total, avail);
eol = findeol(this.buf, this.pos, copy);
if (eol != -1)
copy = eol;
System.arraycopy(this.buf, this.pos, b, off + total, copy);
this.pos += copy;
total += copy;
}
return total;
}
private static int findeol(byte[] b, int pos, int len) {
int end = pos + len;
int i = pos;
while (i < end) {
if (b[i++] == 10)
return i - pos;
}
return -1;
}
public int read() throws IOException {
if (this.count <= this.pos) {
fill();
if (this.count <= this.pos)
return -1;
}
return this.buf[this.pos++] & 0xFF;
}
public int read(byte[] b, int off, int len) throws IOException {
int total = 0;
while (total < len) {
int avail = this.count - this.pos;
if (avail <= 0) {
fill();
avail = this.count - this.pos;
if (avail <= 0) {
if (total > 0)
return total;
return -1;
}
}
int copy = Math.min(len - total, avail);
System.arraycopy(this.buf, this.pos, b, off + total, copy);
this.pos += copy;
total += copy;
}
return total;
}
}

View file

@ -0,0 +1,37 @@
package com.oreilly.servlet.multipart;
import java.io.File;
import java.io.IOException;
public class DefaultFileRenamePolicy implements FileRenamePolicy {
public File rename(File f) {
if (createNewFile(f))
return f;
String name = f.getName();
String body = null;
String ext = null;
int dot = name.lastIndexOf(".");
if (dot != -1) {
body = name.substring(0, dot);
ext = name.substring(dot);
} else {
body = name;
ext = "";
}
int count = 0;
while (!createNewFile(f) && count < 9999) {
count++;
String newName = body + count + ext;
f = new File(f.getParent(), newName);
}
return f;
}
private boolean createNewFile(File f) {
try {
return f.createNewFile();
} catch (IOException ignored) {
return false;
}
}
}

View file

@ -0,0 +1,98 @@
package com.oreilly.servlet.multipart;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletInputStream;
public class FilePart extends Part {
private String fileName;
private String filePath;
private String contentType;
private PartInputStream partInput;
private FileRenamePolicy policy;
FilePart(String name, ServletInputStream in, String boundary, String contentType, String fileName, String filePath) throws IOException {
super(name);
this.fileName = fileName;
this.filePath = filePath;
this.contentType = contentType;
this.partInput = new PartInputStream(in, boundary);
}
public void setRenamePolicy(FileRenamePolicy policy) {
this.policy = policy;
}
public String getFileName() {
return this.fileName;
}
public String getFilePath() {
return this.filePath;
}
public String getContentType() {
return this.contentType;
}
public InputStream getInputStream() {
return this.partInput;
}
public long writeTo(File fileOrDirectory) throws IOException {
long written = 0L;
OutputStream fileOut = null;
try {
if (this.fileName != null) {
File file;
if (fileOrDirectory.isDirectory()) {
file = new File(fileOrDirectory, this.fileName);
} else {
file = fileOrDirectory;
}
if (this.policy != null) {
file = this.policy.rename(file);
this.fileName = file.getName();
}
fileOut = new BufferedOutputStream(new FileOutputStream(file));
written = write(fileOut);
}
} finally {
if (fileOut != null)
fileOut.close();
}
return written;
}
public long writeTo(OutputStream out) throws IOException {
long size = 0L;
if (this.fileName != null)
size = write(out);
return size;
}
long write(OutputStream out) throws IOException {
if (this.contentType.equals("application/x-macbinary"))
out = new MacBinaryDecoderOutputStream(out);
long size = 0L;
byte[] buf = new byte[8192];
int read;
while ((read = this.partInput.read(buf)) != -1) {
out.write(buf, 0, read);
size += (long)read;
}
return size;
}
public boolean isFile() {
return true;
}
}

View file

@ -0,0 +1,7 @@
package com.oreilly.servlet.multipart;
import java.io.File;
public interface FileRenamePolicy {
File rename(File paramFile);
}

View file

@ -0,0 +1,46 @@
package com.oreilly.servlet.multipart;
import java.io.IOException;
import javax.servlet.ServletInputStream;
public class LimitedServletInputStream extends ServletInputStream {
private ServletInputStream in;
private int totalExpected;
private int totalRead = 0;
public LimitedServletInputStream(ServletInputStream in, int totalExpected) {
this.in = in;
this.totalExpected = totalExpected;
}
public int readLine(byte[] b, int off, int len) throws IOException {
int left = this.totalExpected - this.totalRead;
if (left <= 0)
return -1;
int result = this.in.readLine(b, off, Math.min(left, len));
if (result > 0)
this.totalRead += result;
return result;
}
public int read() throws IOException {
if (this.totalRead >= this.totalExpected)
return -1;
int result = this.in.read();
if (result != -1)
this.totalRead++;
return result;
}
public int read(byte[] b, int off, int len) throws IOException {
int left = this.totalExpected - this.totalRead;
if (left <= 0)
return -1;
int result = this.in.read(b, off, Math.min(left, len));
if (result > 0)
this.totalRead += result;
return result;
}
}

View file

@ -0,0 +1,41 @@
package com.oreilly.servlet.multipart;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class MacBinaryDecoderOutputStream extends FilterOutputStream {
private int bytesFiltered = 0;
private int dataForkLength = 0;
public MacBinaryDecoderOutputStream(OutputStream out) {
super(out);
}
public void write(int b) throws IOException {
if (this.bytesFiltered <= 86 && this.bytesFiltered >= 83) {
int leftShift = (86 - this.bytesFiltered) * 8;
this.dataForkLength |= (b & 0xFF) << leftShift;
} else if (this.bytesFiltered < 128 + this.dataForkLength && this.bytesFiltered >= 128) {
this.out.write(b);
}
this.bytesFiltered++;
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
if (this.bytesFiltered >= 128 + this.dataForkLength) {
this.bytesFiltered += len;
} else if (this.bytesFiltered >= 128 && this.bytesFiltered + len <= 128 + this.dataForkLength) {
this.out.write(b, off, len);
this.bytesFiltered += len;
} else {
for (int i = 0; i < len; i++)
write(b[off + i]);
}
}
}

View file

@ -0,0 +1,209 @@
package com.oreilly.servlet.multipart;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
public class MultipartParser {
private ServletInputStream in;
private String boundary;
private FilePart lastFilePart;
private byte[] buf;
private static String DEFAULT_ENCODING = "ISO-8859-1";
private String encoding;
public MultipartParser(HttpServletRequest req, int maxSize) throws IOException {
this(req, maxSize, true, true);
}
public MultipartParser(HttpServletRequest req, int maxSize, boolean buffer, boolean limitLength) throws IOException {
this(req, maxSize, buffer, limitLength, null);
}
public MultipartParser(HttpServletRequest req, int maxSize, boolean buffer, boolean limitLength, String encoding) throws IOException {
String line;
this.buf = new byte[8192];
this.encoding = DEFAULT_ENCODING;
if (encoding != null)
setEncoding(encoding);
String type = null;
String type1 = req.getHeader("Content-Type");
String type2 = req.getContentType();
if (type1 == null && type2 != null) {
type = type2;
} else if (type2 == null && type1 != null) {
type = type1;
} else if (type1 != null && type2 != null) {
type = (type1.length() > type2.length()) ? type1 : type2;
}
if (type == null || !type.toLowerCase().startsWith("multipart/form-data"))
throw new IOException("Posted content type isn't multipart/form-data");
int length = req.getContentLength();
if (length > maxSize)
throw new IOException("Posted content length of " + length + " exceeds limit of " + maxSize);
String boundary = extractBoundary(type);
if (boundary == null)
throw new IOException("Separation boundary was not specified");
ServletInputStream in = req.getInputStream();
if (buffer)
in = new BufferedServletInputStream(in);
if (limitLength)
in = new LimitedServletInputStream(in, length);
this.in = in;
this.boundary = boundary;
do {
line = readLine();
if (line == null)
throw new IOException("Corrupt form data: premature ending");
} while (!line.startsWith(boundary));
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public Part readNextPart() throws IOException {
if (this.lastFilePart != null) {
this.lastFilePart.getInputStream().close();
this.lastFilePart = null;
}
Vector headers = new Vector();
String line = readLine();
if (line == null)
return null;
if (line.length() == 0)
return null;
while (line != null && line.length() > 0) {
String nextLine = null;
boolean getNextLine = true;
while (getNextLine) {
nextLine = readLine();
if (nextLine != null && (nextLine.startsWith(" ") || nextLine.startsWith("\t"))) {
line = line + nextLine;
continue;
}
getNextLine = false;
}
headers.addElement(line);
line = nextLine;
}
if (line == null)
return null;
String name = null;
String filename = null;
String origname = null;
String contentType = "text/plain";
Enumeration enum = headers.elements();
while (enum.hasMoreElements()) {
String headerline = (String)enum.nextElement();
if (headerline.toLowerCase().startsWith("content-disposition:")) {
String[] dispInfo = extractDispositionInfo(headerline);
name = dispInfo[1];
filename = dispInfo[2];
origname = dispInfo[3];
continue;
}
if (headerline.toLowerCase().startsWith("content-type:")) {
String type = extractContentType(headerline);
if (type != null)
contentType = type;
}
}
if (filename == null)
return new ParamPart(name, this.in, this.boundary, this.encoding);
if (filename.equals(""))
filename = null;
this.lastFilePart = new FilePart(name, this.in, this.boundary, contentType, filename, origname);
return this.lastFilePart;
}
private String extractBoundary(String line) {
int index = line.lastIndexOf("boundary=");
if (index == -1)
return null;
String boundary = line.substring(index + 9);
if (boundary.charAt(0) == '"') {
index = boundary.lastIndexOf('"');
boundary = boundary.substring(1, index);
}
boundary = "--" + boundary;
return boundary;
}
private String[] extractDispositionInfo(String line) throws IOException {
String[] retval = new String[4];
String origline = line;
line = origline.toLowerCase();
int start = line.indexOf("content-disposition: ");
int end = line.indexOf(";");
if (start == -1 || end == -1)
throw new IOException("Content disposition corrupt: " + origline);
String disposition = line.substring(start + 21, end);
if (!disposition.equals("form-data"))
throw new IOException("Invalid content disposition: " + disposition);
start = line.indexOf("name=\"", end);
end = line.indexOf("\"", start + 7);
int startOffset = 6;
if (start == -1 || end == -1) {
start = line.indexOf("name=", end);
end = line.indexOf(";", start + 6);
if (start == -1)
throw new IOException("Content disposition corrupt: " + origline);
if (end == -1)
end = line.length();
startOffset = 5;
}
String name = origline.substring(start + startOffset, end);
String filename = null;
String origname = null;
start = line.indexOf("filename=\"", end + 2);
end = line.indexOf("\"", start + 10);
if (start != -1 && end != -1) {
filename = origline.substring(start + 10, end);
origname = filename;
int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
if (slash > -1)
filename = filename.substring(slash + 1);
}
retval[0] = disposition;
retval[1] = name;
retval[2] = filename;
retval[3] = origname;
return retval;
}
private static String extractContentType(String line) throws IOException {
line = line.toLowerCase();
int end = line.indexOf(";");
if (end == -1)
end = line.length();
return line.substring(13, end).trim();
}
private String readLine() throws IOException {
int result;
StringBuffer sbuf = new StringBuffer();
do {
result = this.in.readLine(this.buf, 0, this.buf.length);
if (result == -1)
continue;
sbuf.append(new String(this.buf, 0, result, this.encoding));
} while (result == this.buf.length);
if (sbuf.length() == 0)
return null;
int len = sbuf.length();
if (len >= 2 && sbuf.charAt(len - 2) == '\r') {
sbuf.setLength(len - 2);
} else if (len >= 1 && sbuf.charAt(len - 1) == '\n') {
sbuf.setLength(len - 1);
}
return sbuf.toString();
}
}

View file

@ -0,0 +1,42 @@
package com.oreilly.servlet.multipart;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletInputStream;
public class ParamPart extends Part {
private byte[] value;
private String encoding;
ParamPart(String name, ServletInputStream in, String boundary, String encoding) throws IOException {
super(name);
this.encoding = encoding;
PartInputStream pis = new PartInputStream(in, boundary);
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
byte[] buf = new byte[128];
int read;
while ((read = pis.read(buf)) != -1)
baos.write(buf, 0, read);
pis.close();
baos.close();
this.value = baos.toByteArray();
}
public byte[] getValue() {
return this.value;
}
public String getStringValue() throws UnsupportedEncodingException {
return getStringValue(this.encoding);
}
public String getStringValue(String encoding) throws UnsupportedEncodingException {
return new String(this.value, encoding);
}
public boolean isParam() {
return true;
}
}

View file

@ -0,0 +1,21 @@
package com.oreilly.servlet.multipart;
public abstract class Part {
private String name;
Part(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public boolean isFile() {
return false;
}
public boolean isParam() {
return false;
}
}

View file

@ -0,0 +1,109 @@
package com.oreilly.servlet.multipart;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletInputStream;
public class PartInputStream extends FilterInputStream {
private String boundary;
private byte[] buf = new byte[65536];
private int count;
private int pos;
private boolean eof;
PartInputStream(ServletInputStream in, String boundary) throws IOException {
super((InputStream)in);
this.boundary = boundary;
}
private void fill() throws IOException {
if (this.eof)
return;
if (this.count > 0)
if (this.count - this.pos == 2) {
System.arraycopy(this.buf, this.pos, this.buf, 0, this.count - this.pos);
this.count -= this.pos;
this.pos = 0;
} else {
throw new IllegalStateException("fill() detected illegal buffer state");
}
int read = 0;
int boundaryLength = this.boundary.length();
int maxRead = this.buf.length - boundaryLength - 2;
while (this.count < maxRead) {
read = ((ServletInputStream)this.in).readLine(this.buf, this.count, this.buf.length - this.count);
if (read == -1)
throw new IOException("unexpected end of part");
if (read >= boundaryLength) {
this.eof = true;
for (int i = 0; i < boundaryLength; i++) {
if (this.boundary.charAt(i) != this.buf[this.count + i]) {
this.eof = false;
break;
}
}
if (this.eof)
break;
}
this.count += read;
}
}
public int read() throws IOException {
if (this.count - this.pos <= 2) {
fill();
if (this.count - this.pos <= 2)
return -1;
}
return this.buf[this.pos++] & 0xFF;
}
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException {
int total = 0;
if (len == 0)
return 0;
int avail = this.count - this.pos - 2;
if (avail <= 0) {
fill();
avail = this.count - this.pos - 2;
if (avail <= 0)
return -1;
}
int copy = Math.min(len, avail);
System.arraycopy(this.buf, this.pos, b, off, copy);
this.pos += copy;
total += copy;
while (total < len) {
fill();
avail = this.count - this.pos - 2;
if (avail <= 0)
return total;
copy = Math.min(len - total, avail);
System.arraycopy(this.buf, this.pos, b, off + total, copy);
this.pos += copy;
total += copy;
}
return total;
}
public int available() throws IOException {
int avail = this.count - this.pos - 2 + this.in.available();
return (avail < 0) ? 0 : avail;
}
public void close() throws IOException {
if (!this.eof)
do {
} while (read(this.buf, 0, this.buf.length) != -1);
}
}