org.cybergarage.http.HTTPPacket Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of upnp-stack-jdk13 Show documentation
Show all versions of upnp-stack-jdk13 Show documentation
A pure Java Open Source implementation of the UPnP stack backported for JDK13
The newest version!
/******************************************************************
*
* CyberHTTP for Java
*
* Copyright (C) Satoshi Konno 2002-2004
*
* File: HTTPConnection.java
*
* Revision;
*
* 11/18/02
* - first revision.
* 09/02/03
* - Giordano Sassaroli
* - Problem : The API is unable to receive responses from the Microsoft UPnP stack
* - Error : the Microsoft UPnP stack is based on ISAPI on IIS, and whenever IIS
* receives a post request, it answers with two responses: the first one has no
* body and it is a code 100 (continue) response, which has to be ignored. The
* second response is the actual one and should be parsed as the response.
* 02/09/04
* - Ralf G. R. Bergs"
* - Why do you strip leading and trailing white space from the response body?
* - Disabled to trim the content string.
* 03/11/04
* - Added some methods about InputStream content.
* setContentInputStream(), getContentInputStream() and hasContentInputStream().
* 03/16/04
* - Thanks for Darrell Young
* - Added setVersion() and getVersion();
* 03/17/04
* - Added hasFirstLine();
* 05/26/04
* - Jan Newmarch (05/26/04)
* - Changed setCacheControl() and getChcheControl();
* 08/25/04
* - Added the following methods.
* hasContentRange(), setContentRange(), getContentRange(),
* getContentRangeFirstPosition(), getContentRangeLastPosition() and getContentRangeInstanceLength()
* 08/26/04
* - Added the following methods.
* hasConnection(), setConnection(), getConnection(),
* isCloseConnection() and isKeepAliveConnection()
* 08/27/04
* - Added a updateWithContentLength paramger to setContent().
* - Changed to HTTPPacket::set() not to change the header of Content-Length.
* 08/28/04
* - Added init() and read().
* 09/19/04
* - Added a onlyHeaders parameter to set().
* 10/20/04
* - Brent Hills
* - Changed hasContentRange() to check Content-Range and Range header.
* - Added support for Range header to getContentRange().
* 02/02/05
* - Mark Retallack
* - Fixed set() not to read over the content length when the stream is keep alive.
* 02/28/05
* - Added the following methods for chunked stream support.
* hasTransferEncoding(), setTransferEncoding(), getTransferEncoding(), isChunked().
* 03/02/05
* - Changed post() to suppot chunked stream.
* 06/11/05
* - Added setHost().
* 07/07/05
* - Lee Peik Feng
* - Andrey Ovchar
* - Fixed set() to parse the chunk size as a hex string.
* 11/02/05
* - Changed set() to use BufferedInputStream instead of BufferedReader to
* get the content as a byte stream.
* 11/06/05
* - Added getCharSet().
* - Changed getContentString() to return the content string using the charset.
*
*******************************************************************/
package org.cybergarage.http;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.Calendar;
import java.util.StringTokenizer;
import java.util.Vector;
import org.cybergarage.net.HostInterface;
import org.cybergarage.util.Debug;
import org.cybergarage.util.StringUtil;
public class HTTPPacket
{
////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////
public HTTPPacket()
{
setVersion(HTTP.VERSION);
setContentInputStream(null);
}
public HTTPPacket(HTTPPacket httpPacket)
{
setVersion(HTTP.VERSION);
set(httpPacket);
setContentInputStream(null);
}
public HTTPPacket(InputStream in)
{
setVersion(HTTP.VERSION);
set(in);
setContentInputStream(null);
}
////////////////////////////////////////////////
// init
////////////////////////////////////////////////
public void init()
{
setFirstLine("");
clearHeaders();
setContent(new byte[0], false);
setContentInputStream(null);
}
////////////////////////////////////////////////
// Version
////////////////////////////////////////////////
private String version;
public void setVersion(String ver)
{
version = ver;
}
public String getVersion()
{
return version;
}
////////////////////////////////////////////////
// set
////////////////////////////////////////////////
private String readLine(BufferedInputStream in)
{
ByteArrayOutputStream lineBuf = new ByteArrayOutputStream();
byte readBuf[] = new byte[1];
try {
int readLen = in.read(readBuf);
while (0 < readLen) {
if (readBuf[0] == HTTP.LF)
break;
if (readBuf[0] != HTTP.CR)
lineBuf.write(readBuf[0]);
readLen = in.read(readBuf);
}
}
catch (InterruptedIOException e) {
//Ignoring warning because it's a way to break the HTTP connecttion
//TODO Create a new level of Logging and log the event
}
catch (IOException e) {
Debug.warning(e);
}
return lineBuf.toString();
}
protected boolean set(InputStream in, boolean onlyHeaders)
{
try {
BufferedInputStream reader = new BufferedInputStream(in);
String firstLine = readLine(reader);
if (firstLine == null || firstLine.length() <= 0)
return false;
setFirstLine(firstLine);
// Thanks for Giordano Sassaroli (09/03/03)
HTTPStatus httpStatus = new HTTPStatus(firstLine);
int statCode = httpStatus.getStatusCode();
if (statCode == HTTPStatus.CONTINUE){
//ad hoc code for managing iis non-standard behaviour
//iis sends 100 code response and a 200 code response in the same
//stream, so the code should check the presence of the actual
//response in the stream.
//skip all header lines
String headerLine = readLine(reader);
while ((headerLine != null) && (0 < headerLine.length()) ) {
HTTPHeader header = new HTTPHeader(headerLine);
if (header.hasName() == true)
setHeader(header);
headerLine = readLine(reader);
}
//look forward another first line
String actualFirstLine = readLine(reader);
if ((actualFirstLine != null) && (0 < actualFirstLine.length()) ) {
//this is the actual first line
setFirstLine(actualFirstLine);
}else{
return true;
}
}
String headerLine = readLine(reader);
while ((headerLine != null) && (0 < headerLine.length()) ) {
HTTPHeader header = new HTTPHeader(headerLine);
if (header.hasName() == true)
setHeader(header);
headerLine = readLine(reader);
}
if (onlyHeaders == true) {
setContent("", false);
return true;
}
boolean isChunkedRequest = isChunked();
long contentLen = 0;
if (isChunkedRequest == true) {
try {
String chunkSizeLine = readLine(reader);
// Thanks for Lee Peik Feng (07/07/05)
contentLen = Long.parseLong(new String(chunkSizeLine.getBytes(), 0, chunkSizeLine.length()-2), 16);
}
catch (Exception e) {};
}
else
contentLen = getContentLength();
ByteArrayOutputStream contentBuf = new ByteArrayOutputStream();
while (0 < contentLen) {
int chunkSize = HTTP.getChunkSize();
byte readBuf[] = new byte[chunkSize];
long readCnt = 0;
while (readCnt < contentLen) {
try {
// Thanks for Mark Retallack (02/02/05)
long bufReadLen = contentLen - readCnt;
if (chunkSize < bufReadLen)
bufReadLen = chunkSize;
int readLen = reader.read(readBuf, 0, (int)bufReadLen);
if (readLen < 0)
break;
contentBuf.write(readBuf, 0, readLen);
readCnt += readLen;
}
catch (Exception e)
{
Debug.warning(e);
break;
}
}
if (isChunkedRequest == true) {
// skip CRLF
long skipLen = 0;
do {
long skipCnt = reader.skip(HTTP.CRLF.length() - skipLen);
if (skipCnt < 0)
break;
skipLen += skipCnt;
} while (skipLen < HTTP.CRLF.length());
// read next chunk size
try {
String chunkSizeLine = readLine(reader);
// Thanks for Lee Peik Feng (07/07/05)
contentLen = Long.parseLong(new String(chunkSizeLine.getBytes(), 0, chunkSizeLine.length()-2), 16);
}
catch (Exception e) {
contentLen = 0;
};
}
else
contentLen = 0;
}
setContent(contentBuf.toByteArray(), false);
}
catch (Exception e) {
Debug.warning(e);
return false;
}
return true;
}
protected boolean set(InputStream in)
{
return set(in, false);
}
protected boolean set(HTTPSocket httpSock)
{
return set(httpSock.getInputStream());
}
protected void set(HTTPPacket httpPacket)
{
setFirstLine(httpPacket.getFirstLine());
clearHeaders();
int nHeaders = httpPacket.getNHeaders();
for (int n=0; n 0) ? true : false;
}
////////////////////////////////////////////////
// Contents (InputStream)
////////////////////////////////////////////////
private InputStream contentInput = null;
public void setContentInputStream(InputStream in)
{
contentInput = in;
}
public InputStream getContentInputStream()
{
return contentInput;
}
public boolean hasContentInputStream()
{
return (contentInput != null) ? true : false;
}
////////////////////////////////////////////////
// ContentType
////////////////////////////////////////////////
public void setContentType(String type)
{
setHeader(HTTP.CONTENT_TYPE, type);
}
public String getContentType()
{
return getHeaderValue(HTTP.CONTENT_TYPE);
}
////////////////////////////////////////////////
// Charset
////////////////////////////////////////////////
public String getCharSet()
{
String contentType = getContentType();
if (contentType == null)
return "";
contentType = contentType.toLowerCase();
int charSetIdx = contentType.indexOf(HTTP.CHARSET);
if (charSetIdx < 0)
return "";
int charSetEndIdx = charSetIdx + HTTP.CHARSET.length() + 1;
String charSet = new String(contentType.getBytes(), charSetEndIdx, (contentType.length() - charSetEndIdx));
if (charSet.length() < 0)
return "";
if (charSet.charAt(0) == '\"')
charSet = charSet.substring(1, (charSet.length() - 1));
if (charSet.length() < 0)
return "";
if (charSet.charAt((charSet.length()-1)) == '\"')
charSet = charSet.substring(0, (charSet.length() - 1));
return charSet;
}
////////////////////////////////////////////////
// ContentLength
////////////////////////////////////////////////
public void setContentLength(long len)
{
setLongHeader(HTTP.CONTENT_LENGTH, len);
}
public long getContentLength()
{
return getLongHeaderValue(HTTP.CONTENT_LENGTH);
}
////////////////////////////////////////////////
// Connection
////////////////////////////////////////////////
public boolean hasConnection()
{
return hasHeader(HTTP.CONNECTION);
}
public void setConnection(String value)
{
setHeader(HTTP.CONNECTION, value);
}
public String getConnection()
{
return getHeaderValue(HTTP.CONNECTION);
}
public boolean isCloseConnection()
{
if (hasConnection() == false)
return false;
String connection = getConnection();
if (connection == null)
return false;
return connection.equalsIgnoreCase(HTTP.CLOSE);
}
public boolean isKeepAliveConnection()
{
if (hasConnection() == false)
return false;
String connection = getConnection();
if (connection == null)
return false;
return connection.equalsIgnoreCase(HTTP.KEEP_ALIVE);
}
////////////////////////////////////////////////
// ContentRange
////////////////////////////////////////////////
public boolean hasContentRange()
{
return (hasHeader(HTTP.CONTENT_RANGE) || hasHeader(HTTP.RANGE));
}
public void setContentRange(long firstPos, long lastPos, long length)
{
String rangeStr = "";
rangeStr += HTTP.CONTENT_RANGE_BYTES + " ";
rangeStr += Long.toString(firstPos) + "-";
rangeStr += Long.toString(lastPos) + "/";
rangeStr += ((0 < length) ? Long.toString(length) : "*");
setHeader(HTTP.CONTENT_RANGE, rangeStr);
}
public long[] getContentRange()
{
long range[] = new long[3];
range[0] = range[1] = range[2] = 0;
if (hasContentRange() == false)
return range;
String rangeLine = getHeaderValue(HTTP.CONTENT_RANGE);
// Thanks for Brent Hills (10/20/04)
if (rangeLine.length() <= 0)
rangeLine = getHeaderValue(HTTP.RANGE);
if (rangeLine.length() <= 0)
return range;
// Thanks for Brent Hills (10/20/04)
StringTokenizer strToken = new StringTokenizer(rangeLine, " =");
// Skip bytes
if (strToken.hasMoreTokens() == false)
return range;
String bytesStr = strToken.nextToken(" ");
// Get first-byte-pos
if (strToken.hasMoreTokens() == false)
return range;
String firstPosStr = strToken.nextToken(" -");
try {
range[0] = Long.parseLong(firstPosStr);
}
catch (NumberFormatException e) {};
if (strToken.hasMoreTokens() == false)
return range;
String lastPosStr = strToken.nextToken("-/");
try {
range[1] = Long.parseLong(lastPosStr);
}
catch (NumberFormatException e) {};
if (strToken.hasMoreTokens() == false)
return range;
String lengthStr = strToken.nextToken("/");
try {
range[2] = Long.parseLong(lengthStr);
}
catch (NumberFormatException e) {};
return range;
}
public long getContentRangeFirstPosition()
{
long range[] = getContentRange();
return range[0];
}
public long getContentRangeLastPosition()
{
long range[] = getContentRange();
return range[1];
}
public long getContentRangeInstanceLength()
{
long range[] = getContentRange();
return range[2];
}
////////////////////////////////////////////////
// CacheControl
////////////////////////////////////////////////
public void setCacheControl(String directive)
{
setHeader(HTTP.CACHE_CONTROL, directive);
}
public void setCacheControl(String directive, int value)
{
String strVal = directive + "=" + Integer.toString(value);
setHeader(HTTP.CACHE_CONTROL, strVal);
}
public void setCacheControl(int value)
{
setCacheControl(HTTP.MAX_AGE, value);
}
public String getCacheControl()
{
return getHeaderValue(HTTP.CACHE_CONTROL);
}
////////////////////////////////////////////////
// Server
////////////////////////////////////////////////
public void setServer(String name)
{
setHeader(HTTP.SERVER, name);
}
public String getServer()
{
return getHeaderValue(HTTP.SERVER);
}
////////////////////////////////////////////////
// Host
////////////////////////////////////////////////
public void setHost(String host, int port)
{
String hostAddr = host;
setHeader(HTTP.HOST, hostAddr + ":" + Integer.toString(port));
}
public void setHost(String host)
{
String hostAddr = host;
setHeader(HTTP.HOST, hostAddr);
}
public String getHost()
{
return getHeaderValue(HTTP.HOST);
}
////////////////////////////////////////////////
// Date
////////////////////////////////////////////////
public void setDate(Calendar cal)
{
Date date = new Date(cal);
setHeader(HTTP.DATE, date.getDateString());
}
public String getDate()
{
return getHeaderValue(HTTP.DATE);
}
////////////////////////////////////////////////
// Connection
////////////////////////////////////////////////
public boolean hasTransferEncoding()
{
return hasHeader(HTTP.TRANSFER_ENCODING);
}
public void setTransferEncoding(String value)
{
setHeader(HTTP.TRANSFER_ENCODING, value);
}
public String getTransferEncoding()
{
return getHeaderValue(HTTP.TRANSFER_ENCODING);
}
public boolean isChunked()
{
if (hasTransferEncoding() == false)
return false;
String transEnc = getTransferEncoding();
if (transEnc == null)
return false;
return transEnc.equalsIgnoreCase(HTTP.CHUNKED);
}
////////////////////////////////////////////////
// set
////////////////////////////////////////////////
/*
public final static boolean parse(HTTPPacket httpPacket, InputStream in)
{
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
return parse(httpPacket, reader);
}
catch (Exception e) {
Debug.warning(e);
}
return false;
}
*/
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy