]> git.ipfire.org Git - thirdparty/cups.git/blame - scripting/java/src/com/easysw/cups/IPPHttp.java
Load cups into easysw/current.
[thirdparty/cups.git] / scripting / java / src / com / easysw / cups / IPPHttp.java
CommitLineData
ef416fc2 1package com.easysw.cups;
2
3/**
b86bc4cf 4 * @version 1.1 23-JAN-2007
ef416fc2 5 * @author Easy Software Products
6 *
7 * Internet Printing Protocol definitions for the Common UNIX Printing
8 * System (CUPS).
9 *
b86bc4cf 10 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 11 *
12 * These coded instructions, statements, and computer programs are the
13 * property of Easy Software Products and are protected by Federal
14 * copyright law. Distribution and use rights are outlined in the file
15 * "LICENSE.txt" which should have been included with this file. If this
16 * file is missing or damaged please contact Easy Software Products
17 * at:
18 *
19 * Attn: CUPS Licensing Information
20 * Easy Software Products
21 * 44141 Airport View Drive, Suite 204
b86bc4cf 22 * Hollywood, Maryland 20636 USA
ef416fc2 23 *
b86bc4cf 24 * Voice: (301) 373-9600
ef416fc2 25 * EMail: cups-info@cups.org
b86bc4cf 26 * WWW: http://www.cups.org/
ef416fc2 27 */
28
29/**
30 * An <code>IPPHttp</code> object is used for reading/writing to the cups
31 * server, and processing responses.
32 *
33 * @author TDB
b86bc4cf 34 * @version 1.1
ef416fc2 35 * @since JDK1.3
36 */
37
38import java.io.*;
39import java.util.*;
40import java.net.*;
41import java.security.*;
42
43public class IPPHttp
44{
45
46 /**
47 * Class constants - most not in use yet.
48 */
49 public static final int HTTP_WAITING = 0x00;
50 public static final int HTTP_OPTIONS = 0x01;
51 public static final int HTTP_GET = 0x02;
52 public static final int HTTP_GET_SEND = 0x03;
53 public static final int HTTP_HEAD = 0x04;
54 public static final int HTTP_POST = 0x05;
55 public static final int HTTP_POST_RECV = 0x06;
56 public static final int HTTP_POST_SEND = 0x07;
57 public static final int HTTP_PUT = 0x08;
58 public static final int HTTP_PUT_RECV = 0x09;
59 public static final int HTTP_DELETE = 0x0A;
60 public static final int HTTP_TRACE = 0x0B;
61 public static final int HTTP_CLOSE = 0x0C;
62 public static final int HTTP_STATUS = 0x0D;
63
64 public static final int HTTP_0_9 = 0x09;
65 public static final int HTTP_1_0 = 0x64;
66 public static final int HTTP_1_1 = 0x65;
67
68 public static final int HTTP_KEEPALIVE_OFF = 0x00;
69 public static final int HTTP_KEEPALIVE_ON = 0x01;
70
71 public static final int HTTP_ENCODE_LENGTH = 0x00;
72 public static final int HTTP_ENCODE_CHUNKED = 0x01;
73
74 public static final int HTTP_ENCRYPT_IF_REQUESTED = 0x00;
75 public static final int HTTP_ENCRYPT_NEVER = 0x01;
76 public static final int HTTP_ENCRYPT_REQUIRED = 0x02;
77 public static final int HTTP_ENCRYPT_ALWAYS = 0x03;
78
79 public static final int HTTP_AUTH_NONE = 0x00;
80 public static final int HTTP_AUTH_BASIC = 0x01;
81 public static final int HTTP_AUTH_MD5 = 0x02;
82 public static final int HTTP_AUTH_MD5_SESS = 0x03;
83 public static final int HTTP_AUTH_MD5_INT = 0x04;
84 public static final int HTTP_AUTH_MD5_SESS_INT = 0x05;
85
86 public static final int HTTP_ERROR = 0xFFFFFFFF;
87 public static final int HTTP_CONTINUE = 0x64;
88 public static final int HTTP_SWITCHING_PROTOCOLS = 0x65;
89 public static final int HTTP_OK = 0xC8;
90 public static final int HTTP_CREATED = 0xC9;
91 public static final int HTTP_ACCEPTED = 0xCA;
92 public static final int HTTP_NOT_AUTHORITATIVE = 0xCB;
93 public static final int HTTP_NO_CONTENT = 0xCC;
94 public static final int HTTP_RESET_CONTENT = 0xCD;
95 public static final int HTTP_PARTIAL_CONTENT = 0xCE;
96 public static final int HTTP_MULTIPLE_CHOICES = 0x12C;
97 public static final int HTTP_MOVED_PERMANENTLY = 0x12D;
98 public static final int HTTP_MOVED_TEMPORARILY = 0x12E;
99 public static final int HTTP_SEE_OTHER = 0x12F;
100 public static final int HTTP_NOT_MODIFIED = 0x130;
101 public static final int HTTP_USE_PROXY = 0x131;
102 public static final int HTTP_BAD_REQUEST = 0x190;
103 public static final int HTTP_UNAUTHORIZED = 0x191;
104 public static final int HTTP_PAYMENT_REQUIRED = 0x192;
105 public static final int HTTP_FORBIDDEN = 0x193;
106 public static final int HTTP_NOT_FOUND = 0x194;
107 public static final int HTTP_METHOD_NOT_ALLOWED = 0x195;
108 public static final int HTTP_NOT_ACCEPTABLE = 0x196;
109 public static final int HTTP_PROXY_AUTHENTICATION = 0x197;
110 public static final int HTTP_REQUEST_TIMEOUT = 0x198;
111 public static final int HTTP_CONFLICT = 0x199;
112 public static final int HTTP_GONE = 0x19A;
113 public static final int HTTP_LENGTH_REQUIRED = 0x19B;
114 public static final int HTTP_PRECONDITION = 0x19C;
115 public static final int HTTP_REQUEST_TOO_LARGE = 0x19D;
116 public static final int HTTP_URI_TOO_LONG = 0x19E;
117 public static final int HTTP_UNSUPPORTED_MEDIATYPE = 0x19F;
118 public static final int HTTP_UPGRADE_REQUIRED = 0x1AA;
119 public static final int HTTP_SERVER_ERROR = 0x1F4;
120 public static final int HTTP_NOT_IMPLEMENTED = 0x1F5;
121 public static final int HTTP_BAD_GATEWAY = 0x1F6;
122 public static final int HTTP_SERVICE_UNAVAILABLE = 0x1F7;
123 public static final int HTTP_GATEWAY_TIMEOUT = 0x1F8;
124
125 public static final int HTTP_NOT_SUPPORTED = 0x1F9;
126
127 public static final int HTTP_FIELD_UNKNOWN = 0xFFFFFFFF;
128 public static final int HTTP_FIELD_ACCEPT_LANGUAGE = 0x00;
129 public static final int HTTP_FIELD_ACCEPT_RANGES = 0x01;
130 public static final int HTTP_FIELD_AUTHORIZATION = 0x02;
131 public static final int HTTP_FIELD_CONNECTION = 0x03;
132 public static final int HTTP_FIELD_CONTENT_ENCODING = 0x04;
133 public static final int HTTP_FIELD_CONTENT_LANGUAGE = 0x05;
134 public static final int HTTP_FIELD_CONTENT_LENGTH = 0x06;
135 public static final int HTTP_FIELD_CONTENT_LOCATION = 0x07;
136 public static final int HTTP_FIELD_CONTENT_MD5 = 0x08;
137 public static final int HTTP_FIELD_CONTENT_RANGE = 0x09;
138 public static final int HTTP_FIELD_CONTENT_TYPE = 0x0A;
139 public static final int HTTP_FIELD_CONTENT_VERSION = 0x0B;
140 public static final int HTTP_FIELD_DATE = 0x0C;
141 public static final int HTTP_FIELD_HOST = 0x0D;
142 public static final int HTTP_FIELD_IF_MODIFIED_SINCE = 0x0E;
143 public static final int HTTP_FIELD_IF_UNMODIFIED_SINCE = 0x0F;
144 public static final int HTTP_FIELD_KEEP_ALIVE = 0x10;
145 public static final int HTTP_FIELD_LAST_MODIFIED = 0x11;
146 public static final int HTTP_FIELD_LINK = 0x12;
147 public static final int HTTP_FIELD_LOCATION = 0x13;
148 public static final int HTTP_FIELD_RANGE = 0x14;
149 public static final int HTTP_FIELD_REFERER = 0x15;
150 public static final int HTTP_FIELD_RETRY_AFTER = 0x16;
151 public static final int HTTP_FIELD_TRANSFER_ENCODING = 0x17;
152 public static final int HTTP_FIELD_UPGRADE = 0x18;
153 public static final int HTTP_FIELD_USER_AGENT = 0x19;
154 public static final int HTTP_FIELD_WWW_AUTHENTICATE = 0x1A;
155 public static final int HTTP_FIELD_MAX = 0x1B;
156
157 public static final String http_fields[] =
158 {
159 "Accept-Language",
160 "Accept-Ranges",
161 "Authorization",
162 "Connection",
163 "Content-Encoding",
164 "Content-Language",
165 "Content-Length",
166 "Content-Location",
167 "Content-MD5",
168 "Content-Range",
169 "Content-Type",
170 "Content-Version",
171 "Date",
172 "Host",
173 "If-Modified-Since",
174 "If-Unmodified-since",
175 "Keep-Alive",
176 "Last-Modified",
177 "Link",
178 "Location",
179 "Range",
180 "Referer",
181 "Retry-After",
182 "Transfer-Encoding",
183 "Upgrade",
184 "User-Agent",
185 "WWW-Authenticate"
186 };
187 public static final String days[] =
188 {
189 "Sun",
190 "Mon",
191 "Tue",
192 "Wed",
193 "Thu",
194 "Fri",
195 "Sat"
196 };
197 public static final String months[] =
198 {
199 "Jan",
200 "Feb",
201 "Mar",
202 "Apr",
203 "May",
204 "Jun",
205 "Jul",
206 "Aug",
207 "Sep",
208 "Oct",
209 "Nov",
210 "Dec"
211 };
212
213
214
215 //
216 // Private class members.
217 //
218 private URL url; // URL of connection.
219
220 public Socket conn; // Connection socket.
221 public boolean connected; // True when connected.
222
223 public BufferedInputStream is; // Input stream.
224 public BufferedReader br;
225 public BufferedOutputStream os; // Output stream.
226
227 private boolean encrypted;
228
229 public int write_content_length;
230 private char write_buffer[];
231 private int write_buffer_head;
232 private int write_buffer_tail;
233
234 public String read_header_date;
235 public String read_header_server;
236 public String read_header_charset;
237 public String read_header_content_language;
238 public String read_header_content_type;
239 public int read_header_content_length;
240
241 public char read_buffer[];
242 private int read_buffer_head;
243 private int read_buffer_tail;
244
245 public int status;
246 public String status_text;
247 public String version;
248 public int error;
249 public int activity;
250
251 public String hostname; // Hostname from URL
252 public int port; // Port from URL.
253 public String path; // Path from URL.
254 public String user; // User name
255 public String passwd; // Password
256
257 public String auth_type; // none, basic, digest
258 public String realm; // For digest auth
259 public String opaque; // For digest auth
260 public String nonce; // For digest auth
261 public String resource; // For digest auth
262 public String method; // For digest auth
263
264 public String http_request;
265 public int http_content_length;
266
267
268
269 /**
270 * Constructor using <code>URL</code>.
271 *
272 * @param request_url <code>URL</code> of server to connect to.
273 * @throw IOException
274 * @throw UnknownHostException
275 */
276 public IPPHttp( String request_url )
277 throws IOException, UnknownHostException
278 {
279
280 encrypted = false;
281 status = 0;
282 status_text = "";
283 version = "1.0";
284 connected = false;
285 user = "";
286 passwd = "";
287
288 auth_type = "";
289 realm = "";
290 nonce = "";
291 resource = "";
292 method = "";
293
294 try
295 {
296 //
297 // Create the URL and split it up.
298 //
299 url = new URL(request_url);
300 hostname = url.getHost();
301 port = url.getPort();
302 path = url.getPath();
303
304
305 //
306 // Open the socket and set the options.
307 //
308 conn = new Socket(hostname, port);
309 conn.setSoTimeout(200);
310
311 //
312 // Create the input and output streams.
313 //
314 is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
315 os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
316 connected = true;
317 }
318 catch(UnknownHostException unknownhostexception)
319 {
320 throw unknownhostexception;
321 }
322 catch(IOException ioexception)
323 {
324 throw ioexception;
325 }
326 }
327
328
329
330 /**
331 * Constructor using <code>URL, user and pass</code>.
332 *
333 * @param request_url <code>URL</code> of server to connect to.
334 * @param p_auth_type <code>String</code> basic or digest.
335 * @param p_user <code>String</code> User name.
336 * @param p_passwd <code>String</code> password.
337 * @throw IOException
338 * @throw UnknownHostException
339 */
340 public IPPHttp( String request_url, String p_auth_type,
341 String p_user, String p_passwd )
342 throws IOException, UnknownHostException
343 {
344 encrypted = false;
345 status = 0;
346 status_text = "";
347 version = "1.0";
348 connected = false;
349
350 user = p_user;
351 passwd = p_passwd;
352 auth_type = p_auth_type;
353
354 realm = "";
355 nonce = "";
356 resource = "";
357 method = "";
358
359 try
360 {
361 //
362 // Create the URL and split it up.
363 //
364 url = new URL(request_url);
365 hostname = url.getHost();
366 port = url.getPort();
367 path = url.getPath();
368
369 //
370 // Open the socket and set the options.
371 //
372 conn = new Socket(hostname, port);
373 conn.setSoTimeout(200);
374
375 //
376 // Create the input and output streams.
377 //
378 is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
379 os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
380 connected = true;
381 }
382 catch(UnknownHostException unknownhostexception)
383 {
384 throw unknownhostexception;
385 }
386 catch(IOException ioexception)
387 {
388 throw ioexception;
389 }
390 }
391
392
393
394
395 /**
396 * Re-establish a dropped connection.
397 *
398 * @return <code>boolean</code> True if connected.
399 *
400 * @throw IOException
401 */
402 public boolean reConnect() throws IOException
403 {
404 connected = false;
405 status = 0;
406 status_text = "";
407 try
408 {
409 //
410 // Open the socket and set the options.
411 //
412 conn = new Socket(hostname, port);
413 conn.setSoTimeout(200);
414
415 //
416 // Create the input and output streams.
417 //
418 is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
419 os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
420 connected = true;
421 return(connected);
422
423 }
424 catch (IOException ioexception)
425 {
426 connected = false;
427 throw(ioexception);
428 }
429 }
430
431
432
433 /**
434 * Set the user name.
435 *
436 * @param p_user <code>String</code> - user name.
437 */
438 public void setUser(String p_user )
439 {
440 user = p_user;
441 }
442
443
444 /**
445 * Set the password.
446 *
447 * @param p_passwd <code>String</code> - password.
448 */
449 public void setPassword(String p_passwd )
450 {
451 passwd = p_passwd;
452 }
453
454
455
456
457 /**
458 * Write the request header bytes to the server.
459 *
460 * @param request <code>String</code> - the request.
461 * @param content_length <code>int</code> - size of the total request.
462 * @throw IOException
463 */
464 public int writeHeader(String request, int content_length )
465 throws IOException
466 {
467
468 http_request = request;
469 http_content_length = content_length;
470
471 try
472 {
473 String s1 = "POST " + request + " HTTP/1.0\r\n";
474 os.write(s1.getBytes(), 0, s1.length());
475
476 s1 = "Content-type: application/ipp\r\n";
477 os.write(s1.getBytes(), 0, s1.length());
478
479
480 //
481 // Do basic style authorization if needed.
482 //
483 if (auth_type.compareTo("basic") == 0)
484 {
485 s1 = user + ":" + passwd;
b86bc4cf 486 String auth_string = Base64Coder.encodeString(s1);
ef416fc2 487 s1 = "Authorization: Basic " + auth_string + "\r\n";
488 os.write(s1.getBytes(), 0, s1.length());
489 }
490 else if (auth_type.compareTo("digest") == 0)
491 {
492 try
493 {
494 IPPMD5 md5 = IPPMD5.getInstance();
495 String auth_string = md5.MD5Digest(user, passwd, realm,
496 "POST", path, nonce );
497 s1 = "Authorization: Digest " + "username=\"" + user + "\", " +
498 "realm=\"" + realm + "\", " +
499 "nonce=\"" + nonce + "\", " +
500 "response=\"" + auth_string + "\"\r\n";
501
502 os.write(s1.getBytes(), 0, s1.length());
503 }
504 catch(NoSuchAlgorithmException e)
505 {
506 System.out.println("No such algorithm: MD5.");
507 }
508 }
509
510 s1 = "Content-length: " + content_length + "\r\n\r\n";
511 os.write(s1.getBytes(), 0, s1.length());
512 os.flush();
513 }
514 catch(IOException ioexception)
515 {
516 error = HTTP_ERROR;
517 throw ioexception;
518 }
519
520
521 try
522 {
523 int local_status = 0;
524
525 //
526 // Check for any response.
527 //
528 if (is.available() > 0)
529 {
530 StringBuffer http_version = new StringBuffer(32);
531 StringBuffer http_status = new StringBuffer(32);
532 StringBuffer http_text = new StringBuffer(256);
533
534 String read_buffer;
535 status = 0;
536 is.mark(8192);
537 while (is.available() > 0)
538 {
539 read_buffer = read_line();
540
541 if (read_buffer.startsWith("HTTP/"))
542 {
543 int i,n;
544 String s2 = read_buffer.substring(5);
545
546
547 for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
548 {
549 http_version.append(s2.charAt(i));
550 }
551 while (i < s2.length() && s2.charAt(i) == ' ')
552 i++;
553 for (;(i < s2.length() && s2.charAt(i) != '\n' &&
554 s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
555 {
556 http_status.append(s2.charAt(i));
557 }
558
559 while (i < s2.length() && s2.charAt(i) == ' ')
560 i++;
561 for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
562 s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
563 {
564 http_text.append(s2.charAt(i));
565 }
566 local_status = Integer.parseInt(http_status.toString(), 10);
567 }
568 }
569 is.reset();
570 }
571
572 //
573 // See if we need to reconnect and send authorization.
574 //
575 switch( local_status )
576 {
577 //
578 // Not authorized.
579 //
580 case HTTP_UNAUTHORIZED: read_header();
581 return( local_status );
582 }
583 }
584 catch(IOException ioexception)
585 {
586 error = HTTP_ERROR;
587 throw ioexception;
588 }
589 return(0);
590 }
591
592
593
594
595
596
597 public int checkForResponse()
598 {
599 //
600 // Check for any response.
601 //
602 try
603 {
604 if (is.available() > 0)
605 {
606 StringBuffer http_version = new StringBuffer(32);
607 StringBuffer http_status = new StringBuffer(32);
608 StringBuffer http_text = new StringBuffer(256);
609 int local_status = 0;
610 String read_buffer;
611
612 status = 0;
613 is.mark(8192);
614 while (is.available() > 0)
615 {
616 read_buffer = read_line();
617 if (read_buffer.startsWith("HTTP/"))
618 {
619 int i,n;
620 String s2 = read_buffer.substring(5);
621 for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
622 {
623 http_version.append(s2.charAt(i));
624 }
625 while (i < s2.length() && s2.charAt(i) == ' ')
626 i++;
627 for (;(i < s2.length() && s2.charAt(i) != '\n' &&
628 s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
629 {
630 http_status.append(s2.charAt(i));
631 }
632
633 while (i < s2.length() && s2.charAt(i) == ' ')
634 i++;
635 for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
636 s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
637 {
638 http_text.append(s2.charAt(i));
639 }
640 local_status = Integer.parseInt(http_status.toString(), 10);
641 status = local_status;
642 }
643 }
644 is.reset();
645
646 //
647 // See if we need to reconnect and send authorization.
648 //
649 switch( local_status )
650 {
651 //
652 // Not authorized.
653 //
654 case HTTP_UNAUTHORIZED: read_header();
655 return( local_status );
656 }
657 }
658 }
659 catch (IOException e)
660 {
661 return(HTTP_ERROR);
662 }
663 return(0);
664 }
665
666
667 /**
668 * Write bytes to the output stream.
669 *
670 * @param bytes Array of bytes to write to the stream.
671 * @throw IOException
672 */
673 public void write(byte bytes[])
674 throws IOException
675 {
676 try
677 {
678 os.write(bytes, 0, bytes.length);
679 os.flush();
680 }
681 catch(IOException ioexception)
682 {
683 error = HTTP_ERROR;
684 throw ioexception;
685 }
686 }
687
688
689 /**
690 * Write bytes to the output stream.
691 *
692 * @param bytes Array of bytes to write to the stream.
693 * @param length Number of bytes to write to the stream.
694 * @throw IOException
695 */
696 public void write(byte bytes[], int length )
697 throws IOException
698 {
699 try
700 {
701 os.write(bytes, 0, length);
702 os.flush();
703 }
704 catch(IOException ioexception)
705 {
706 error = HTTP_ERROR;
707 throw ioexception;
708 }
709 }
710
711
712
713
714
715
716
717
718
719
720 /**
721 * Read the HTTP header from the input stream.
722 *
723 * @return <code>int</code> Content length of response.
724 * @return 0 Return zero on error.
725 * @throw IOException
726 */
727 public int read_header()
728 throws IOException
729 {
730 boolean done = false;
731 read_header_content_length = 0;
732
733 String read_buffer;
734 while (!done)
735 {
736 read_buffer = read_line();
737 if (read_buffer.startsWith("HTTP/"))
738 {
739 int i,n;
740 String s2 = read_buffer.substring(5);
741
742 StringBuffer http_version = new StringBuffer(32);
743 StringBuffer http_status = new StringBuffer(32);
744 StringBuffer http_text = new StringBuffer(256);
745
746 for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
747 {
748 http_version.append(s2.charAt(i));
749 }
750 while (i < s2.length() && s2.charAt(i) == ' ')
751 i++;
752 for (;(i < s2.length() && s2.charAt(i) != '\n' &&
753 s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
754 {
755 http_status.append(s2.charAt(i));
756 }
757
758 while (i < s2.length() && s2.charAt(i) == ' ')
759 i++;
760 for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
761 s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
762 {
763 http_text.append(s2.charAt(i));
764 }
765 version = http_version.toString();
766 status = Integer.parseInt(http_status.toString(), 10);
767 status_text = http_text.toString();
768 }
769 else if (read_buffer.startsWith("WWW-Authenticate: Basic"))
770 {
771 String s2=read_buffer.substring("WWW-Authenticate: Basic".length());
772 auth_type = "basic";
773 }
774 else if (read_buffer.startsWith("WWW-Authenticate: Digest"))
775 {
776 String s2=read_buffer.substring("WWW-Authenticate: Digest".length());
777 auth_type = "digest";
778 parseAuthenticate(s2);
779 }
780 else if (read_buffer.startsWith("Content-Length:"))
781 {
782 String s2 = read_buffer.substring(15);
783 read_header_content_length = Integer.parseInt(s2.trim(), 10);
784 }
785 else if (read_buffer.startsWith("Content-Language:"))
786 {
787 String s3 = read_buffer.substring(17);
788 read_header_content_language = s3.trim();
789 }
790 else if (read_buffer.startsWith("Server:"))
791 {
792 String s4 = read_buffer.substring(7);
793 read_header_server = s4.trim();
794 }
795 else if (read_buffer.startsWith("Date:"))
796 {
797 String s5 = read_buffer.substring(5);
798 read_header_date = s5.trim();
799 }
800 else if (read_buffer.length() == 0)
801 {
802 done = true;
803 return( read_header_content_length );
804 }
805 }
806 return( 0 );
807 }
808
809
810
811 /**
812 * Read a line from the input stream.
813 *
814 * @return <code>String</code> Line read.
815 * @throw <code>IOException</code>
816 */
817 public String read_line()
818 throws IOException
819 {
820 StringBuffer sb = new StringBuffer();
821 int c = 0;
822
823 try
824 {
825 while ((c != -1) && (c != 10))
826 {
827 c = is.read();
828 switch( c )
829 {
830 case -1:
831 case 10:
832 case 13:
833 break;
834
835 default: sb.append((char)c);
836 }
837 }
838 }
839 catch (IOException e)
840 {
841 throw(e);
842 }
843 return(sb.toString());
844 }
845
846
847
848
849
850 /**
851 * Read up to <code>count</code> bytes from the input stream.
852 *
853 * @param <code>count</code> Number of bytes to read.
854 * @return <code>char[]</code> Character array of data read.
855 * @throw <code>IOException</code>
856 */
857 public char[] read(int count)
858 throws IOException
859 {
860 char ac[] = new char[count];
861 int j = 0;
862 try
863 {
864 for (int k = is.read(); k != -1 && j < count; k = is.read())
865 {
866 ac[j++] = (char)k;
867 }
868 }
869 catch(IOException ioexception)
870 {
871 throw ioexception;
872 }
873 return(ac);
874 }
875
876
877 /**
878 * Process the HTTP response from the server.
879 *
880 * @return <code>IPP</code> IPP object containing response data.
881 * @see <code>IPP</code>
882 * @see <code>IPPRequest</code>
883 * @see <code>IPPAttribute</code>
884 * @see <code>IPPValue</code>
885 * @see <code>IPPDefs</code>
886 */
887 public IPP processResponse()
888 {
889 IPP ipp;
890 IPPAttribute attr; // temp attribute
891 IPPValue val; // temp value
892
893 short vtag; // Current value tag
894 short gtag; // Current group tag
895
896 char[] buffer;
897
898 ipp = new IPP();
899 ipp.request = new IPPRequest();
900
901 int read_buffer_bytes = read_buffer.length;
902 int read_buffer_remaining = read_buffer_bytes;
903 int bufferidx = 0;
904 int n;
905
906
907 ipp.current = -1; // current attritue??
908 ipp.last = -1; // last attr?
909 attr = null;
910 buffer = read_buffer;
911 gtag = -1;
912 vtag = -1;
913
914
915 // ---------------------------------------------------------------
916 // State machine to process response.
917 //
918 ipp.state = IPPDefs.IDLE;
919 while ((ipp.state != IPPDefs.TAG_END) &&
920 (read_buffer_remaining > 0))
921 {
922 switch (ipp.state)
923 {
924 case IPPDefs.IDLE :
925 ipp.state++; /* Avoid common problem... */
926
927 //
928 // Get the request header...
929 //
930 case IPPDefs.HEADER :
931 if (read_buffer_remaining < 8)
932 {
933 return (null);
934 }
935
936 //
937 // Verify the major version number...
938 //
939 if (buffer[0] != (char)1)
940 {
941 return (null);
942 }
943
944 //
945 // Then copy the request header over...
946 //
947 ipp.request.version[0] = buffer[bufferidx++];
948 ipp.request.version[1] = buffer[bufferidx++];
949 ipp.request.op_status = (short)((short)buffer[bufferidx] << 8) |
950 (short)buffer[bufferidx+1];
951 bufferidx += 2;
952
953 //
954 // Get the text version of the request status ....
955 //
956 ipp.status = new IPPStatus(ipp.request.op_status);
957
958 ipp.request.request_id = (int)((int)buffer[bufferidx] << 24) |
959 ((int)buffer[bufferidx+1] << 16) |
960 ((int)buffer[bufferidx+2] << 8) |
961 ((int)buffer[bufferidx+3]);
962 bufferidx += 4;
963 read_buffer_remaining -= 8;
964
965 ipp.state = IPPDefs.ATTRIBUTE;
966 ipp.current = -1;
967 ipp.current_tag = IPPDefs.TAG_ZERO;
968 break;
969
970 case IPPDefs.ATTRIBUTE :
971 while (read_buffer_remaining > 0)
972 {
973 //
974 // Read the value tag first.
975 //
976 vtag = (short)buffer[bufferidx++];
977 read_buffer_remaining--;
978 if (vtag == IPPDefs.TAG_END)
979 {
980 //
981 // No more attributes left...
982 //
983 ipp.state = IPPDefs.DATA;
984 if (attr != null)
985 {
986 ipp.addAttribute(attr);
987 attr = null;
988 }
989 break;
990 }
991 else if (vtag < IPPDefs.TAG_UNSUPPORTED_VALUE)
992 {
993 if (attr != null)
994 {
995 ipp.addAttribute(attr);
996 }
997
998 //
999 // Group tag... Set the current group and continue...
1000 //
1001 gtag = vtag;
1002
1003 // If still the same group ....
1004 if (ipp.current_tag == gtag)
1005 {
1006 //
1007 // Add a separator
1008 //
1009 attr = new IPPAttribute(IPPDefs.TAG_ZERO,IPPDefs.TAG_ZERO,"");
1010 ipp.addAttribute(attr);
1011 attr = null;
1012 }
1013
1014
1015 ipp.current_tag = gtag;
1016 ipp.current = -1;
1017 continue;
1018 }
1019
1020 //
1021 // Get the name...
1022 //
1023 n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
1024 bufferidx += 2;
1025 read_buffer_remaining -= 2;
1026
1027 if (n == 0)
1028 {
1029 //
1030 // Parse Error, can't add additional values to null attr
1031 //
1032 if (attr == null)
1033 return (null);
1034
1035 //
1036 // More values for current attribute...
1037 //
1038
1039 //
1040 // Make sure we aren't adding a new value of a different
1041 // type...
1042 //
1043
1044 if (attr.value_tag == IPPDefs.TAG_STRING ||
1045 (attr.value_tag >= IPPDefs.TAG_TEXTLANG &&
1046 attr.value_tag <= IPPDefs.TAG_MIMETYPE))
1047 {
1048 //
1049 // String values can sometimes come across in different
1050 // forms; accept sets of differing values...
1051 //
1052 if (vtag != IPPDefs.TAG_STRING &&
1053 (vtag < IPPDefs.TAG_TEXTLANG || vtag > IPPDefs.TAG_MIMETYPE))
1054 return (null);
1055 }
1056 else if (attr.value_tag != vtag)
1057 return (null);
1058 }
1059 else
1060 {
1061 if (attr != null)
1062 {
1063 ipp.addAttribute(attr);
1064 attr = null;
1065 }
1066
1067 //
1068 // New Attribute
1069 //
1070 StringBuffer s = new StringBuffer();
1071 for (int i=0; i < n; i++)
1072 {
1073 s.append((char)buffer[bufferidx++]);
1074 read_buffer_remaining--;
1075 }
1076 attr = new IPPAttribute( gtag, vtag, s.toString() );
1077 }
1078 n = ((short)buffer[bufferidx] << 8) | (short)buffer[bufferidx+1];
1079 bufferidx += 2;
1080 read_buffer_remaining -= 2;
1081
1082 switch (vtag)
1083 {
1084 case IPPDefs.TAG_INTEGER :
1085 case IPPDefs.TAG_ENUM :
1086 n = (int)(((int)buffer[bufferidx] << 24) |
1087 ((int)buffer[bufferidx+1] << 16) |
1088 ((int)buffer[bufferidx+2] << 8) |
1089 ((int)buffer[bufferidx+3]));
1090 bufferidx += 4;
1091 read_buffer_remaining -= 4;
1092 attr.addInteger( n );
1093 break;
1094
1095 case IPPDefs.TAG_BOOLEAN :
1096 if ((byte)buffer[bufferidx++] > 0)
1097 attr.addBoolean(true);
1098 else
1099 attr.addBoolean(false);
1100 read_buffer_remaining --;
1101 break;
1102
1103 case IPPDefs.TAG_TEXT :
1104 case IPPDefs.TAG_NAME :
1105 case IPPDefs.TAG_KEYWORD :
1106 case IPPDefs.TAG_STRING :
1107 case IPPDefs.TAG_URI :
1108 case IPPDefs.TAG_URISCHEME :
1109 case IPPDefs.TAG_CHARSET :
1110 case IPPDefs.TAG_LANGUAGE :
1111 case IPPDefs.TAG_MIMETYPE :
1112 StringBuffer s = new StringBuffer();
1113 for (int i=0; i < n; i++ )
1114 {
1115 s.append( (char)buffer[bufferidx++] );
1116 read_buffer_remaining --;
1117 }
1118 attr.addString( "", s.toString() );
1119 break;
1120
1121
1122 case IPPDefs.TAG_DATE :
1123 char db[] = new char[11];
1124 for (int i=0; i < 11; i++ )
1125 {
1126 db[i] = (char)buffer[bufferidx++];
1127 read_buffer_remaining --;
1128 }
1129 attr.addDate( db );
1130 break;
1131
1132
1133 case IPPDefs.TAG_RESOLUTION :
1134 if (read_buffer_remaining < 9)
1135 return( null );
1136
1137 int x, y;
1138 byte u;
1139 x = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
1140 (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
1141 (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
1142 (((int)buffer[bufferidx+3] & 0x000000ff));
1143 bufferidx += 4;
1144 read_buffer_remaining -= 4;
1145
1146 y = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
1147 (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
1148 (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
1149 (((int)buffer[bufferidx+3] & 0x000000ff));
1150 bufferidx += 4;
1151 read_buffer_remaining -= 4;
1152
1153 u = (byte)buffer[bufferidx++];
1154 read_buffer_remaining--;
1155 attr.addResolution( u, x, y );
1156 break;
1157
1158 case IPPDefs.TAG_RANGE :
1159 if (read_buffer_remaining < 8)
1160 return (null);
1161
1162 int lower, upper;
1163 lower = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
1164 (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
1165 (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
1166 (((int)buffer[bufferidx+3] & 0x000000ff));
1167 bufferidx += 4;
1168 read_buffer_remaining -= 4;
1169
1170 upper = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
1171 (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
1172 (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
1173 (((int)buffer[bufferidx+3] & 0x000000ff));
1174 bufferidx += 4;
1175 read_buffer_remaining -= 4;
1176
1177 attr.addRange( (short)lower, (short)upper );
1178 break;
1179
1180 case IPPDefs.TAG_TEXTLANG :
1181 case IPPDefs.TAG_NAMELANG :
1182 //
1183 // text-with-language and name-with-language are composite
1184 // values:
1185 //
1186 // charset-length
1187 // charset
1188 // text-length
1189 // text
1190 //
1191
1192 n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
1193 bufferidx += 2;
1194
1195 StringBuffer cs = new StringBuffer();
1196 for (int i=0; i < n; i++ )
1197 {
1198 cs.append( (char)buffer[bufferidx++] );
1199 read_buffer_remaining --;
1200 }
1201
1202 n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
1203 bufferidx += 2;
1204
1205 StringBuffer tx = new StringBuffer();
1206 for (int i=0; i < n; i++ )
1207 {
1208 tx.append( (char)buffer[bufferidx++] );
1209 read_buffer_remaining --;
1210 }
1211
1212 attr.addString( cs.toString(), tx.toString() );
1213 break;
1214
1215
1216 default : /* Other unsupported values */
1217 if (n > 0)
1218 {
1219 bufferidx += n;
1220 read_buffer_remaining -= n;
1221 }
1222 break;
1223 }
1224 } // End of while
1225
1226 if (attr != null)
1227 {
1228 ipp.addAttribute(attr);
1229 attr = null;
1230 }
1231 break;
1232
1233 case IPPDefs.DATA :
1234 break;
1235
1236 default :
1237 break; /* anti-compiler-warning-code */
1238 }
1239 }
1240 return (ipp);
1241}
1242
1243
1244
1245//
1246// Parse a WWW-Authenticate: Digest request
1247//
1248public void parseAuthenticate( String p_auth )
1249{
1250 String tmp;
1251 StringBuffer val;
1252 int i,n;
1253
1254 tmp = p_auth;
1255 while (tmp.length() > 0)
1256 {
1257 i = 0;
1258 while (tmp.length() > 0 && (tmp.charAt(i) == ' ' || tmp.charAt(i) == '"'))
1259 tmp = tmp.substring(1);
1260 i = 0;
1261
1262 if (tmp.startsWith("realm="))
1263 {
1264 i = "realm=".length();
1265 tmp = tmp.substring(i);
1266 i = 0;
1267 while ((i < tmp.length()) &&
1268 (tmp.charAt(i) == ' ' ||
1269 tmp.charAt(i) == '"' ||
1270 tmp.charAt(i) == '='))
1271 {
1272 i++;
1273 }
1274 val = new StringBuffer(1024);
1275 while (i < tmp.length() && tmp.charAt(i) != '"')
1276 val.append(tmp.charAt(i++));
1277 realm = val.toString();
1278 tmp = tmp.substring(i);
1279 }
1280 else if (tmp.startsWith("nonce="))
1281 {
1282 i = "nonce=".length();
1283 tmp = tmp.substring(i);
1284 i = 0;
1285 while ((i < tmp.length()) &&
1286 (tmp.charAt(i) == ' ' ||
1287 tmp.charAt(i) == '"' ||
1288 tmp.charAt(i) == '='))
1289 {
1290 i++;
1291 }
1292 val = new StringBuffer(1024);
1293 while (i < tmp.length() && tmp.charAt(i) != '"')
1294 val.append(tmp.charAt(i++));
1295 nonce = val.toString();
1296 tmp = tmp.substring(i);
1297 }
1298 else if (tmp.startsWith("opaque="))
1299 {
1300 i = "opaque=".length();
1301 tmp = tmp.substring(i);
1302 i = 0;
1303 while ((i < tmp.length()) &&
1304 (tmp.charAt(i) == ' ' ||
1305 tmp.charAt(i) == '"' ||
1306 tmp.charAt(i) == '='))
1307 {
1308 i++;
1309 }
1310 val = new StringBuffer(1024);
1311 while (i < tmp.length() && tmp.charAt(i) != '"')
1312 val.append(tmp.charAt(i++));
1313 opaque = val.toString();
1314 tmp = tmp.substring(i);
1315 }
1316 else
1317 {
1318 StringBuffer name = new StringBuffer(256);
1319 while ((i < tmp.length()) &&
1320 (tmp.charAt(i) != ' ' ||
1321 tmp.charAt(i) != '"' ||
1322 tmp.charAt(i) != '='))
1323 {
1324 name.append(tmp.charAt(i++));
1325 }
1326
1327 i = name.toString().length();
1328 tmp = tmp.substring(i);
1329 i = 0;
1330 while ((i < tmp.length()) &&
1331 (tmp.charAt(i) == ' ' ||
1332 tmp.charAt(i) == '"' ||
1333 tmp.charAt(i) == '='))
1334 {
1335 i++;
1336 }
1337 val = new StringBuffer(1024);
1338 while (i < tmp.length() && tmp.charAt(i) != '"')
1339 val.append(tmp.charAt(i++));
1340 //junk = val.toString();
1341 tmp = tmp.substring(i);
1342 }
1343 }
1344}
1345
1346
1347
1348
1349
1350} // End of IPPHttp class
1351
1352