All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.archive.format.http.HttpResponseMessageParser Maven / Gradle / Ivy

The newest version!
package org.archive.format.http;

import java.io.IOException;
import java.io.InputStream;

public class HttpResponseMessageParser extends HttpMessageParser {
	public int maxBytes = 1024 * 128;
	public boolean strict = false;

	public HttpResponseMessage parseMessage(InputStream is) 
	throws HttpParseException, IOException {

		HttpResponseMessage message = new HttpResponseMessage();
		parse(is,message);
		return message;
	}

	public int parse(InputStream is, HttpResponseMessageObserver obs) 
	throws HttpParseException, IOException {
		int bytesRead = 0;
		
		byte buf[] = new byte[maxBytes];
		
		while(bytesRead < maxBytes) {
			int i = is.read();
			if(i == -1) {
				if(strict) {
					throw new HttpParseException("EOF before CRLF");
				}
				obs.messageCorrupt();
				return bytesRead;
			}
			if(i > 127) {
				if(strict) {
					throw new HttpParseException("Non ASCII byte in message");
				}
				obs.messageCorrupt();
				return bytesRead;
			}
			byte b = (byte) (i & 0xff);
			buf[bytesRead] = b;
			bytesRead++;
			if(b == LF) {
				return parse(buf,bytesRead,obs);
			}
		}
		// TODO: under Lax consume till EOL and continue?
		throw new HttpParseException("Response Message too long");
	}

	public int parse(byte buf[], int len, HttpResponseMessageObserver obs) 
	throws HttpParseException, IOException {
		return strict ? parseStrict(buf,len,obs) : parseLax(buf,len,obs);
	}

	public int parseStrict(byte buf[], int len, HttpResponseMessageObserver obs) 
	throws HttpParseException, IOException {
		
		if(buf[len-1] != CR) {
			obs.messageCorrupt();
			throw new HttpParseException("Response Message missing CRLF");
		}
		
		int version = VERSION_0;
		int status = 0;
		String reason = REASON_UNK;
		
		int idx = 0;
		int vs = 0;
		int vl = -1;
		int ss = -1;
		int sl = -1;
		while(idx < len) {
			if(buf[idx] != SP) {
				if(ss == -1) {
					// on version:
					vl++;
				} else {
					// on reason:
					vs++;
				}
			} else {
				if(ss == -1) {
					// were on version:
					ss = idx + 1;
				} else {
					break;
				}
			}
			idx++;
		}
		if(idx == len) {
			obs.messageCorrupt();
			throw new HttpParseException("Response Message Missing Fields");
		}
		// found all 3:
		version = parseVersionStrict(buf, vs, vl);
		status = parseStatusStrict(buf,ss,sl);
		
		reason = new String(buf,idx+1,(len - idx)-1);

		obs.messageParsed(version, status, reason, len);

		return len;
	}

	private int parseLax(byte buf[], int len, HttpResponseMessageObserver obs) 
	throws HttpParseException, IOException {
		
		
		int version = VERSION_0;
		int status = 0;
		String reason = REASON_UNK;
		
		// skip leading spaces:
		int idx = 0;
		int vs = -1;
		int vl = 0;
		int ss = -1;
		int sl = 0;
		int bufferEnd = len - 1;
		if((len > 2) && (buf[len - 2] == CR)) {
			bufferEnd--;
		}
		while(idx < bufferEnd) {
			if(buf[idx] != SP) {
				break;
			}
			idx++;
		}
		vs = idx;
		while(idx < bufferEnd) {
			if(buf[idx] != SP) {
				if(ss == -1) {
					// on version:
					vl++;
				} else {
					// on reason:
					sl++;
				}
			} else {
				if(ss == -1) {
					// were on version:
					ss = idx + 1;
				} else {
					break;
				}
			}
			idx++;
		}
		if(idx < bufferEnd) {
			// found all 3:
			version = parseVersionLax(buf, vs, vl);
			status = parseStatusLax(buf,ss,sl);
			idx++;
			int reasonLen = bufferEnd - idx;
			if(reasonLen > 0) {
				reason = new String(buf,idx,reasonLen);
			}
		} else {
			// missed some:
			if(vl > 0) {
				version = parseVersionLax(buf, vs, vl);
			}
			if(sl > 0) {
				status = parseStatusLax(buf,ss,sl);
			}
		}
		
		obs.messageParsed(version, status, reason, len);

		return len;
	}

	private int parseStatusStrict(byte buf[], int start, int len)
	throws HttpParseException {
		int status = 0;
		try {
			int testStatus = Integer.valueOf(new String(buf,start,len,UTF8));
			if((testStatus >= 100) && (testStatus < 600)) {
				status = testStatus;
			}
		} catch (NumberFormatException e) {
		}
		if(status == -1) {
			throw new HttpParseException("Bad status code in Response Message");
		}
		return status;
	}

	private int parseStatusLax(byte buf[], int start, int len)
	throws HttpParseException {
		int status = STATUS_UNK;
		try {
			int testStatus = Integer.valueOf(new String(buf,start,len,UTF8));
			if((testStatus >= 100) && (testStatus < 600)) {
				status = testStatus;
			}
		} catch (NumberFormatException e) {
		}
		return status;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy