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