blob: e5307399f9e686587e8d5c0d9bad5b26c53a6cbd [file] [log] [blame]
package com.easysw.cups;
/**
* @version 1.1 23-JAN-2007
* @author Easy Software Products
*
* Internet Printing Protocol definitions for the Common UNIX Printing
* System (CUPS).
*
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
* property of Easy Software Products and are protected by Federal
* copyright law. Distribution and use rights are outlined in the file
* "LICENSE.txt" which should have been included with this file. If this
* file is missing or damaged please contact Easy Software Products
* at:
*
* Attn: CUPS Licensing Information
* Easy Software Products
* 44141 Airport View Drive, Suite 204
* Hollywood, Maryland 20636 USA
*
* Voice: (301) 373-9600
* EMail: [email protected]
* WWW: http://www.cups.org/
*/
/**
* An <code>IPPHttp</code> object is used for reading/writing to the cups
* server, and processing responses.
*
* @author TDB
* @version 1.1
* @since JDK1.3
*/
import java.io.*;
import java.util.*;
import java.net.*;
import java.security.*;
public class IPPHttp
{
/**
* Class constants - most not in use yet.
*/
public static final int HTTP_WAITING = 0x00;
public static final int HTTP_OPTIONS = 0x01;
public static final int HTTP_GET = 0x02;
public static final int HTTP_GET_SEND = 0x03;
public static final int HTTP_HEAD = 0x04;
public static final int HTTP_POST = 0x05;
public static final int HTTP_POST_RECV = 0x06;
public static final int HTTP_POST_SEND = 0x07;
public static final int HTTP_PUT = 0x08;
public static final int HTTP_PUT_RECV = 0x09;
public static final int HTTP_DELETE = 0x0A;
public static final int HTTP_TRACE = 0x0B;
public static final int HTTP_CLOSE = 0x0C;
public static final int HTTP_STATUS = 0x0D;
public static final int HTTP_0_9 = 0x09;
public static final int HTTP_1_0 = 0x64;
public static final int HTTP_1_1 = 0x65;
public static final int HTTP_KEEPALIVE_OFF = 0x00;
public static final int HTTP_KEEPALIVE_ON = 0x01;
public static final int HTTP_ENCODE_LENGTH = 0x00;
public static final int HTTP_ENCODE_CHUNKED = 0x01;
public static final int HTTP_ENCRYPT_IF_REQUESTED = 0x00;
public static final int HTTP_ENCRYPT_NEVER = 0x01;
public static final int HTTP_ENCRYPT_REQUIRED = 0x02;
public static final int HTTP_ENCRYPT_ALWAYS = 0x03;
public static final int HTTP_AUTH_NONE = 0x00;
public static final int HTTP_AUTH_BASIC = 0x01;
public static final int HTTP_AUTH_MD5 = 0x02;
public static final int HTTP_AUTH_MD5_SESS = 0x03;
public static final int HTTP_AUTH_MD5_INT = 0x04;
public static final int HTTP_AUTH_MD5_SESS_INT = 0x05;
public static final int HTTP_ERROR = 0xFFFFFFFF;
public static final int HTTP_CONTINUE = 0x64;
public static final int HTTP_SWITCHING_PROTOCOLS = 0x65;
public static final int HTTP_OK = 0xC8;
public static final int HTTP_CREATED = 0xC9;
public static final int HTTP_ACCEPTED = 0xCA;
public static final int HTTP_NOT_AUTHORITATIVE = 0xCB;
public static final int HTTP_NO_CONTENT = 0xCC;
public static final int HTTP_RESET_CONTENT = 0xCD;
public static final int HTTP_PARTIAL_CONTENT = 0xCE;
public static final int HTTP_MULTIPLE_CHOICES = 0x12C;
public static final int HTTP_MOVED_PERMANENTLY = 0x12D;
public static final int HTTP_MOVED_TEMPORARILY = 0x12E;
public static final int HTTP_SEE_OTHER = 0x12F;
public static final int HTTP_NOT_MODIFIED = 0x130;
public static final int HTTP_USE_PROXY = 0x131;
public static final int HTTP_BAD_REQUEST = 0x190;
public static final int HTTP_UNAUTHORIZED = 0x191;
public static final int HTTP_PAYMENT_REQUIRED = 0x192;
public static final int HTTP_FORBIDDEN = 0x193;
public static final int HTTP_NOT_FOUND = 0x194;
public static final int HTTP_METHOD_NOT_ALLOWED = 0x195;
public static final int HTTP_NOT_ACCEPTABLE = 0x196;
public static final int HTTP_PROXY_AUTHENTICATION = 0x197;
public static final int HTTP_REQUEST_TIMEOUT = 0x198;
public static final int HTTP_CONFLICT = 0x199;
public static final int HTTP_GONE = 0x19A;
public static final int HTTP_LENGTH_REQUIRED = 0x19B;
public static final int HTTP_PRECONDITION = 0x19C;
public static final int HTTP_REQUEST_TOO_LARGE = 0x19D;
public static final int HTTP_URI_TOO_LONG = 0x19E;
public static final int HTTP_UNSUPPORTED_MEDIATYPE = 0x19F;
public static final int HTTP_UPGRADE_REQUIRED = 0x1AA;
public static final int HTTP_SERVER_ERROR = 0x1F4;
public static final int HTTP_NOT_IMPLEMENTED = 0x1F5;
public static final int HTTP_BAD_GATEWAY = 0x1F6;
public static final int HTTP_SERVICE_UNAVAILABLE = 0x1F7;
public static final int HTTP_GATEWAY_TIMEOUT = 0x1F8;
public static final int HTTP_NOT_SUPPORTED = 0x1F9;
public static final int HTTP_FIELD_UNKNOWN = 0xFFFFFFFF;
public static final int HTTP_FIELD_ACCEPT_LANGUAGE = 0x00;
public static final int HTTP_FIELD_ACCEPT_RANGES = 0x01;
public static final int HTTP_FIELD_AUTHORIZATION = 0x02;
public static final int HTTP_FIELD_CONNECTION = 0x03;
public static final int HTTP_FIELD_CONTENT_ENCODING = 0x04;
public static final int HTTP_FIELD_CONTENT_LANGUAGE = 0x05;
public static final int HTTP_FIELD_CONTENT_LENGTH = 0x06;
public static final int HTTP_FIELD_CONTENT_LOCATION = 0x07;
public static final int HTTP_FIELD_CONTENT_MD5 = 0x08;
public static final int HTTP_FIELD_CONTENT_RANGE = 0x09;
public static final int HTTP_FIELD_CONTENT_TYPE = 0x0A;
public static final int HTTP_FIELD_CONTENT_VERSION = 0x0B;
public static final int HTTP_FIELD_DATE = 0x0C;
public static final int HTTP_FIELD_HOST = 0x0D;
public static final int HTTP_FIELD_IF_MODIFIED_SINCE = 0x0E;
public static final int HTTP_FIELD_IF_UNMODIFIED_SINCE = 0x0F;
public static final int HTTP_FIELD_KEEP_ALIVE = 0x10;
public static final int HTTP_FIELD_LAST_MODIFIED = 0x11;
public static final int HTTP_FIELD_LINK = 0x12;
public static final int HTTP_FIELD_LOCATION = 0x13;
public static final int HTTP_FIELD_RANGE = 0x14;
public static final int HTTP_FIELD_REFERER = 0x15;
public static final int HTTP_FIELD_RETRY_AFTER = 0x16;
public static final int HTTP_FIELD_TRANSFER_ENCODING = 0x17;
public static final int HTTP_FIELD_UPGRADE = 0x18;
public static final int HTTP_FIELD_USER_AGENT = 0x19;
public static final int HTTP_FIELD_WWW_AUTHENTICATE = 0x1A;
public static final int HTTP_FIELD_MAX = 0x1B;
public static final String http_fields[] =
{
"Accept-Language",
"Accept-Ranges",
"Authorization",
"Connection",
"Content-Encoding",
"Content-Language",
"Content-Length",
"Content-Location",
"Content-MD5",
"Content-Range",
"Content-Type",
"Content-Version",
"Date",
"Host",
"If-Modified-Since",
"If-Unmodified-since",
"Keep-Alive",
"Last-Modified",
"Link",
"Location",
"Range",
"Referer",
"Retry-After",
"Transfer-Encoding",
"Upgrade",
"User-Agent",
"WWW-Authenticate"
};
public static final String days[] =
{
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
public static final String months[] =
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
//
// Private class members.
//
private URL url; // URL of connection.
public Socket conn; // Connection socket.
public boolean connected; // True when connected.
public BufferedInputStream is; // Input stream.
public BufferedReader br;
public BufferedOutputStream os; // Output stream.
private boolean encrypted;
public int write_content_length;
private char write_buffer[];
private int write_buffer_head;
private int write_buffer_tail;
public String read_header_date;
public String read_header_server;
public String read_header_charset;
public String read_header_content_language;
public String read_header_content_type;
public int read_header_content_length;
public char read_buffer[];
private int read_buffer_head;
private int read_buffer_tail;
public int status;
public String status_text;
public String version;
public int error;
public int activity;
public String hostname; // Hostname from URL
public int port; // Port from URL.
public String path; // Path from URL.
public String user; // User name
public String passwd; // Password
public String auth_type; // none, basic, digest
public String realm; // For digest auth
public String opaque; // For digest auth
public String nonce; // For digest auth
public String resource; // For digest auth
public String method; // For digest auth
public String http_request;
public int http_content_length;
/**
* Constructor using <code>URL</code>.
*
* @param request_url <code>URL</code> of server to connect to.
* @throw IOException
* @throw UnknownHostException
*/
public IPPHttp( String request_url )
throws IOException, UnknownHostException
{
encrypted = false;
status = 0;
status_text = "";
version = "1.0";
connected = false;
user = "";
passwd = "";
auth_type = "";
realm = "";
nonce = "";
resource = "";
method = "";
try
{
//
// Create the URL and split it up.
//
url = new URL(request_url);
hostname = url.getHost();
port = url.getPort();
path = url.getPath();
//
// Open the socket and set the options.
//
conn = new Socket(hostname, port);
conn.setSoTimeout(200);
//
// Create the input and output streams.
//
is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
connected = true;
}
catch(UnknownHostException unknownhostexception)
{
throw unknownhostexception;
}
catch(IOException ioexception)
{
throw ioexception;
}
}
/**
* Constructor using <code>URL, user and pass</code>.
*
* @param request_url <code>URL</code> of server to connect to.
* @param p_auth_type <code>String</code> basic or digest.
* @param p_user <code>String</code> User name.
* @param p_passwd <code>String</code> password.
* @throw IOException
* @throw UnknownHostException
*/
public IPPHttp( String request_url, String p_auth_type,
String p_user, String p_passwd )
throws IOException, UnknownHostException
{
encrypted = false;
status = 0;
status_text = "";
version = "1.0";
connected = false;
user = p_user;
passwd = p_passwd;
auth_type = p_auth_type;
realm = "";
nonce = "";
resource = "";
method = "";
try
{
//
// Create the URL and split it up.
//
url = new URL(request_url);
hostname = url.getHost();
port = url.getPort();
path = url.getPath();
//
// Open the socket and set the options.
//
conn = new Socket(hostname, port);
conn.setSoTimeout(200);
//
// Create the input and output streams.
//
is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
connected = true;
}
catch(UnknownHostException unknownhostexception)
{
throw unknownhostexception;
}
catch(IOException ioexception)
{
throw ioexception;
}
}
/**
* Re-establish a dropped connection.
*
* @return <code>boolean</code> True if connected.
*
* @throw IOException
*/
public boolean reConnect() throws IOException
{
connected = false;
status = 0;
status_text = "";
try
{
//
// Open the socket and set the options.
//
conn = new Socket(hostname, port);
conn.setSoTimeout(200);
//
// Create the input and output streams.
//
is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
connected = true;
return(connected);
}
catch (IOException ioexception)
{
connected = false;
throw(ioexception);
}
}
/**
* Set the user name.
*
* @param p_user <code>String</code> - user name.
*/
public void setUser(String p_user )
{
user = p_user;
}
/**
* Set the password.
*
* @param p_passwd <code>String</code> - password.
*/
public void setPassword(String p_passwd )
{
passwd = p_passwd;
}
/**
* Write the request header bytes to the server.
*
* @param request <code>String</code> - the request.
* @param content_length <code>int</code> - size of the total request.
* @throw IOException
*/
public int writeHeader(String request, int content_length )
throws IOException
{
http_request = request;
http_content_length = content_length;
try
{
String s1 = "POST " + request + " HTTP/1.0\r\n";
os.write(s1.getBytes(), 0, s1.length());
s1 = "Content-type: application/ipp\r\n";
os.write(s1.getBytes(), 0, s1.length());
//
// Do basic style authorization if needed.
//
if (auth_type.compareTo("basic") == 0)
{
s1 = user + ":" + passwd;
String auth_string = Base64Coder.encodeString(s1);
s1 = "Authorization: Basic " + auth_string + "\r\n";
os.write(s1.getBytes(), 0, s1.length());
}
else if (auth_type.compareTo("digest") == 0)
{
try
{
IPPMD5 md5 = IPPMD5.getInstance();
String auth_string = md5.MD5Digest(user, passwd, realm,
"POST", path, nonce );
s1 = "Authorization: Digest " + "username=\"" + user + "\", " +
"realm=\"" + realm + "\", " +
"nonce=\"" + nonce + "\", " +
"response=\"" + auth_string + "\"\r\n";
os.write(s1.getBytes(), 0, s1.length());
}
catch(NoSuchAlgorithmException e)
{
System.out.println("No such algorithm: MD5.");
}
}
s1 = "Content-length: " + content_length + "\r\n\r\n";
os.write(s1.getBytes(), 0, s1.length());
os.flush();
}
catch(IOException ioexception)
{
error = HTTP_ERROR;
throw ioexception;
}
try
{
int local_status = 0;
//
// Check for any response.
//
if (is.available() > 0)
{
StringBuffer http_version = new StringBuffer(32);
StringBuffer http_status = new StringBuffer(32);
StringBuffer http_text = new StringBuffer(256);
String read_buffer;
status = 0;
is.mark(8192);
while (is.available() > 0)
{
read_buffer = read_line();
if (read_buffer.startsWith("HTTP/"))
{
int i,n;
String s2 = read_buffer.substring(5);
for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
{
http_version.append(s2.charAt(i));
}
while (i < s2.length() && s2.charAt(i) == ' ')
i++;
for (;(i < s2.length() && s2.charAt(i) != '\n' &&
s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
{
http_status.append(s2.charAt(i));
}
while (i < s2.length() && s2.charAt(i) == ' ')
i++;
for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
{
http_text.append(s2.charAt(i));
}
local_status = Integer.parseInt(http_status.toString(), 10);
}
}
is.reset();
}
//
// See if we need to reconnect and send authorization.
//
switch( local_status )
{
//
// Not authorized.
//
case HTTP_UNAUTHORIZED: read_header();
return( local_status );
}
}
catch(IOException ioexception)
{
error = HTTP_ERROR;
throw ioexception;
}
return(0);
}
public int checkForResponse()
{
//
// Check for any response.
//
try
{
if (is.available() > 0)
{
StringBuffer http_version = new StringBuffer(32);
StringBuffer http_status = new StringBuffer(32);
StringBuffer http_text = new StringBuffer(256);
int local_status = 0;
String read_buffer;
status = 0;
is.mark(8192);
while (is.available() > 0)
{
read_buffer = read_line();
if (read_buffer.startsWith("HTTP/"))
{
int i,n;
String s2 = read_buffer.substring(5);
for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
{
http_version.append(s2.charAt(i));
}
while (i < s2.length() && s2.charAt(i) == ' ')
i++;
for (;(i < s2.length() && s2.charAt(i) != '\n' &&
s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
{
http_status.append(s2.charAt(i));
}
while (i < s2.length() && s2.charAt(i) == ' ')
i++;
for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
{
http_text.append(s2.charAt(i));
}
local_status = Integer.parseInt(http_status.toString(), 10);
status = local_status;
}
}
is.reset();
//
// See if we need to reconnect and send authorization.
//
switch( local_status )
{
//
// Not authorized.
//
case HTTP_UNAUTHORIZED: read_header();
return( local_status );
}
}
}
catch (IOException e)
{
return(HTTP_ERROR);
}
return(0);
}
/**
* Write bytes to the output stream.
*
* @param bytes Array of bytes to write to the stream.
* @throw IOException
*/
public void write(byte bytes[])
throws IOException
{
try
{
os.write(bytes, 0, bytes.length);
os.flush();
}
catch(IOException ioexception)
{
error = HTTP_ERROR;
throw ioexception;
}
}
/**
* Write bytes to the output stream.
*
* @param bytes Array of bytes to write to the stream.
* @param length Number of bytes to write to the stream.
* @throw IOException
*/
public void write(byte bytes[], int length )
throws IOException
{
try
{
os.write(bytes, 0, length);
os.flush();
}
catch(IOException ioexception)
{
error = HTTP_ERROR;
throw ioexception;
}
}
/**
* Read the HTTP header from the input stream.
*
* @return <code>int</code> Content length of response.
* @return 0 Return zero on error.
* @throw IOException
*/
public int read_header()
throws IOException
{
boolean done = false;
read_header_content_length = 0;
String read_buffer;
while (!done)
{
read_buffer = read_line();
if (read_buffer.startsWith("HTTP/"))
{
int i,n;
String s2 = read_buffer.substring(5);
StringBuffer http_version = new StringBuffer(32);
StringBuffer http_status = new StringBuffer(32);
StringBuffer http_text = new StringBuffer(256);
for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
{
http_version.append(s2.charAt(i));
}
while (i < s2.length() && s2.charAt(i) == ' ')
i++;
for (;(i < s2.length() && s2.charAt(i) != '\n' &&
s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
{
http_status.append(s2.charAt(i));
}
while (i < s2.length() && s2.charAt(i) == ' ')
i++;
for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
{
http_text.append(s2.charAt(i));
}
version = http_version.toString();
status = Integer.parseInt(http_status.toString(), 10);
status_text = http_text.toString();
}
else if (read_buffer.startsWith("WWW-Authenticate: Basic"))
{
String s2=read_buffer.substring("WWW-Authenticate: Basic".length());
auth_type = "basic";
}
else if (read_buffer.startsWith("WWW-Authenticate: Digest"))
{
String s2=read_buffer.substring("WWW-Authenticate: Digest".length());
auth_type = "digest";
parseAuthenticate(s2);
}
else if (read_buffer.startsWith("Content-Length:"))
{
String s2 = read_buffer.substring(15);
read_header_content_length = Integer.parseInt(s2.trim(), 10);
}
else if (read_buffer.startsWith("Content-Language:"))
{
String s3 = read_buffer.substring(17);
read_header_content_language = s3.trim();
}
else if (read_buffer.startsWith("Server:"))
{
String s4 = read_buffer.substring(7);
read_header_server = s4.trim();
}
else if (read_buffer.startsWith("Date:"))
{
String s5 = read_buffer.substring(5);
read_header_date = s5.trim();
}
else if (read_buffer.length() == 0)
{
done = true;
return( read_header_content_length );
}
}
return( 0 );
}
/**
* Read a line from the input stream.
*
* @return <code>String</code> Line read.
* @throw <code>IOException</code>
*/
public String read_line()
throws IOException
{
StringBuffer sb = new StringBuffer();
int c = 0;
try
{
while ((c != -1) && (c != 10))
{
c = is.read();
switch( c )
{
case -1:
case 10:
case 13:
break;
default: sb.append((char)c);
}
}
}
catch (IOException e)
{
throw(e);
}
return(sb.toString());
}
/**
* Read up to <code>count</code> bytes from the input stream.
*
* @param <code>count</code> Number of bytes to read.
* @return <code>char[]</code> Character array of data read.
* @throw <code>IOException</code>
*/
public char[] read(int count)
throws IOException
{
char ac[] = new char[count];
int j = 0;
try
{
for (int k = is.read(); k != -1 && j < count; k = is.read())
{
ac[j++] = (char)k;
}
}
catch(IOException ioexception)
{
throw ioexception;
}
return(ac);
}
/**
* Process the HTTP response from the server.
*
* @return <code>IPP</code> IPP object containing response data.
* @see <code>IPP</code>
* @see <code>IPPRequest</code>
* @see <code>IPPAttribute</code>
* @see <code>IPPValue</code>
* @see <code>IPPDefs</code>
*/
public IPP processResponse()
{
IPP ipp;
IPPAttribute attr; // temp attribute
IPPValue val; // temp value
short vtag; // Current value tag
short gtag; // Current group tag
char[] buffer;
ipp = new IPP();
ipp.request = new IPPRequest();
int read_buffer_bytes = read_buffer.length;
int read_buffer_remaining = read_buffer_bytes;
int bufferidx = 0;
int n;
ipp.current = -1; // current attritue??
ipp.last = -1; // last attr?
attr = null;
buffer = read_buffer;
gtag = -1;
vtag = -1;
// ---------------------------------------------------------------
// State machine to process response.
//
ipp.state = IPPDefs.IDLE;
while ((ipp.state != IPPDefs.TAG_END) &&
(read_buffer_remaining > 0))
{
switch (ipp.state)
{
case IPPDefs.IDLE :
ipp.state++; /* Avoid common problem... */
//
// Get the request header...
//
case IPPDefs.HEADER :
if (read_buffer_remaining < 8)
{
return (null);
}
//
// Verify the major version number...
//
if (buffer[0] != (char)1)
{
return (null);
}
//
// Then copy the request header over...
//
ipp.request.version[0] = buffer[bufferidx++];
ipp.request.version[1] = buffer[bufferidx++];
ipp.request.op_status = (short)((short)buffer[bufferidx] << 8) |
(short)buffer[bufferidx+1];
bufferidx += 2;
//
// Get the text version of the request status ....
//
ipp.status = new IPPStatus(ipp.request.op_status);
ipp.request.request_id = (int)((int)buffer[bufferidx] << 24) |
((int)buffer[bufferidx+1] << 16) |
((int)buffer[bufferidx+2] << 8) |
((int)buffer[bufferidx+3]);
bufferidx += 4;
read_buffer_remaining -= 8;
ipp.state = IPPDefs.ATTRIBUTE;
ipp.current = -1;
ipp.current_tag = IPPDefs.TAG_ZERO;
break;
case IPPDefs.ATTRIBUTE :
while (read_buffer_remaining > 0)
{
//
// Read the value tag first.
//
vtag = (short)buffer[bufferidx++];
read_buffer_remaining--;
if (vtag == IPPDefs.TAG_END)
{
//
// No more attributes left...
//
ipp.state = IPPDefs.DATA;
if (attr != null)
{
ipp.addAttribute(attr);
attr = null;
}
break;
}
else if (vtag < IPPDefs.TAG_UNSUPPORTED_VALUE)
{
if (attr != null)
{
ipp.addAttribute(attr);
}
//
// Group tag... Set the current group and continue...
//
gtag = vtag;
// If still the same group ....
if (ipp.current_tag == gtag)
{
//
// Add a separator
//
attr = new IPPAttribute(IPPDefs.TAG_ZERO,IPPDefs.TAG_ZERO,"");
ipp.addAttribute(attr);
attr = null;
}
ipp.current_tag = gtag;
ipp.current = -1;
continue;
}
//
// Get the name...
//
n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
bufferidx += 2;
read_buffer_remaining -= 2;
if (n == 0)
{
//
// Parse Error, can't add additional values to null attr
//
if (attr == null)
return (null);
//
// More values for current attribute...
//
//
// Make sure we aren't adding a new value of a different
// type...
//
if (attr.value_tag == IPPDefs.TAG_STRING ||
(attr.value_tag >= IPPDefs.TAG_TEXTLANG &&
attr.value_tag <= IPPDefs.TAG_MIMETYPE))
{
//
// String values can sometimes come across in different
// forms; accept sets of differing values...
//
if (vtag != IPPDefs.TAG_STRING &&
(vtag < IPPDefs.TAG_TEXTLANG || vtag > IPPDefs.TAG_MIMETYPE))
return (null);
}
else if (attr.value_tag != vtag)
return (null);
}
else
{
if (attr != null)
{
ipp.addAttribute(attr);
attr = null;
}
//
// New Attribute
//
StringBuffer s = new StringBuffer();
for (int i=0; i < n; i++)
{
s.append((char)buffer[bufferidx++]);
read_buffer_remaining--;
}
attr = new IPPAttribute( gtag, vtag, s.toString() );
}
n = ((short)buffer[bufferidx] << 8) | (short)buffer[bufferidx+1];
bufferidx += 2;
read_buffer_remaining -= 2;
switch (vtag)
{
case IPPDefs.TAG_INTEGER :
case IPPDefs.TAG_ENUM :
n = (int)(((int)buffer[bufferidx] << 24) |
((int)buffer[bufferidx+1] << 16) |
((int)buffer[bufferidx+2] << 8) |
((int)buffer[bufferidx+3]));
bufferidx += 4;
read_buffer_remaining -= 4;
attr.addInteger( n );
break;
case IPPDefs.TAG_BOOLEAN :
if ((byte)buffer[bufferidx++] > 0)
attr.addBoolean(true);
else
attr.addBoolean(false);
read_buffer_remaining --;
break;
case IPPDefs.TAG_TEXT :
case IPPDefs.TAG_NAME :
case IPPDefs.TAG_KEYWORD :
case IPPDefs.TAG_STRING :
case IPPDefs.TAG_URI :
case IPPDefs.TAG_URISCHEME :
case IPPDefs.TAG_CHARSET :
case IPPDefs.TAG_LANGUAGE :
case IPPDefs.TAG_MIMETYPE :
StringBuffer s = new StringBuffer();
for (int i=0; i < n; i++ )
{
s.append( (char)buffer[bufferidx++] );
read_buffer_remaining --;
}
attr.addString( "", s.toString() );
break;
case IPPDefs.TAG_DATE :
char db[] = new char[11];
for (int i=0; i < 11; i++ )
{
db[i] = (char)buffer[bufferidx++];
read_buffer_remaining --;
}
attr.addDate( db );
break;
case IPPDefs.TAG_RESOLUTION :
if (read_buffer_remaining < 9)
return( null );
int x, y;
byte u;
x = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
(((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
(((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
(((int)buffer[bufferidx+3] & 0x000000ff));
bufferidx += 4;
read_buffer_remaining -= 4;
y = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
(((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
(((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
(((int)buffer[bufferidx+3] & 0x000000ff));
bufferidx += 4;
read_buffer_remaining -= 4;
u = (byte)buffer[bufferidx++];
read_buffer_remaining--;
attr.addResolution( u, x, y );
break;
case IPPDefs.TAG_RANGE :
if (read_buffer_remaining < 8)
return (null);
int lower, upper;
lower = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
(((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
(((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
(((int)buffer[bufferidx+3] & 0x000000ff));
bufferidx += 4;
read_buffer_remaining -= 4;
upper = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
(((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
(((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
(((int)buffer[bufferidx+3] & 0x000000ff));
bufferidx += 4;
read_buffer_remaining -= 4;
attr.addRange( (short)lower, (short)upper );
break;
case IPPDefs.TAG_TEXTLANG :
case IPPDefs.TAG_NAMELANG :
//
// text-with-language and name-with-language are composite
// values:
//
// charset-length
// charset
// text-length
// text
//
n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
bufferidx += 2;
StringBuffer cs = new StringBuffer();
for (int i=0; i < n; i++ )
{
cs.append( (char)buffer[bufferidx++] );
read_buffer_remaining --;
}
n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
bufferidx += 2;
StringBuffer tx = new StringBuffer();
for (int i=0; i < n; i++ )
{
tx.append( (char)buffer[bufferidx++] );
read_buffer_remaining --;
}
attr.addString( cs.toString(), tx.toString() );
break;
default : /* Other unsupported values */
if (n > 0)
{
bufferidx += n;
read_buffer_remaining -= n;
}
break;
}
} // End of while
if (attr != null)
{
ipp.addAttribute(attr);
attr = null;
}
break;
case IPPDefs.DATA :
break;
default :
break; /* anti-compiler-warning-code */
}
}
return (ipp);
}
//
// Parse a WWW-Authenticate: Digest request
//
public void parseAuthenticate( String p_auth )
{
String tmp;
StringBuffer val;
int i,n;
tmp = p_auth;
while (tmp.length() > 0)
{
i = 0;
while (tmp.length() > 0 && (tmp.charAt(i) == ' ' || tmp.charAt(i) == '"'))
tmp = tmp.substring(1);
i = 0;
if (tmp.startsWith("realm="))
{
i = "realm=".length();
tmp = tmp.substring(i);
i = 0;
while ((i < tmp.length()) &&
(tmp.charAt(i) == ' ' ||
tmp.charAt(i) == '"' ||
tmp.charAt(i) == '='))
{
i++;
}
val = new StringBuffer(1024);
while (i < tmp.length() && tmp.charAt(i) != '"')
val.append(tmp.charAt(i++));
realm = val.toString();
tmp = tmp.substring(i);
}
else if (tmp.startsWith("nonce="))
{
i = "nonce=".length();
tmp = tmp.substring(i);
i = 0;
while ((i < tmp.length()) &&
(tmp.charAt(i) == ' ' ||
tmp.charAt(i) == '"' ||
tmp.charAt(i) == '='))
{
i++;
}
val = new StringBuffer(1024);
while (i < tmp.length() && tmp.charAt(i) != '"')
val.append(tmp.charAt(i++));
nonce = val.toString();
tmp = tmp.substring(i);
}
else if (tmp.startsWith("opaque="))
{
i = "opaque=".length();
tmp = tmp.substring(i);
i = 0;
while ((i < tmp.length()) &&
(tmp.charAt(i) == ' ' ||
tmp.charAt(i) == '"' ||
tmp.charAt(i) == '='))
{
i++;
}
val = new StringBuffer(1024);
while (i < tmp.length() && tmp.charAt(i) != '"')
val.append(tmp.charAt(i++));
opaque = val.toString();
tmp = tmp.substring(i);
}
else
{
StringBuffer name = new StringBuffer(256);
while ((i < tmp.length()) &&
(tmp.charAt(i) != ' ' ||
tmp.charAt(i) != '"' ||
tmp.charAt(i) != '='))
{
name.append(tmp.charAt(i++));
}
i = name.toString().length();
tmp = tmp.substring(i);
i = 0;
while ((i < tmp.length()) &&
(tmp.charAt(i) == ' ' ||
tmp.charAt(i) == '"' ||
tmp.charAt(i) == '='))
{
i++;
}
val = new StringBuffer(1024);
while (i < tmp.length() && tmp.charAt(i) != '"')
val.append(tmp.charAt(i++));
//junk = val.toString();
tmp = tmp.substring(i);
}
}
}
} // End of IPPHttp class