home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / net / www / html / messageheader.java < prev    next >
Text File  |  1995-08-11  |  6KB  |  221 lines

  1. /*
  2.  * @(#)MessageHeader.java    1.5 95/05/10 James Gosling, Jonathan Payne
  3.  * 
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for NON-COMMERCIAL purposes and without fee is hereby
  8.  * granted provided that this copyright notice appears in all copies. Please
  9.  * refer to the file "copyright.html" for further important copyright and
  10.  * licensing information.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
  15.  * OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
  16.  * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
  17.  * ITS DERIVATIVES.
  18.  */
  19.  
  20. /*-
  21.  *    news stream opener
  22.  */
  23.  
  24. package net.www.html;
  25.  
  26. import java.io.InputStream;
  27. import java.io.PrintStream;
  28.  
  29. /** An RFC 844 or MIME message header.  Includes methods
  30.     for parsing headers from incoming streams, fetching
  31.     values, setting values, and printing headers.
  32.     Key values of null are legal: they indicate lines in
  33.     the header that don't have a valid key, but do have
  34.     a value (this isn't legal according to the standard,
  35.     but lines like this are everywhere). */
  36. public
  37. class MessageHeader {
  38.     private String keys[];
  39.     private String values[];
  40.     private int nkeys;
  41.  
  42.     public MessageHeader () {
  43.     }
  44.     public MessageHeader (InputStream is) {
  45.     parseHeader(is);
  46.     }
  47.  
  48.     /** Find the value that corresponds to this key.
  49.     It finds only the first occurrance of the key.
  50.     Returns null if not found. */
  51.     public String findValue(String k) {
  52.     if (k == null) {
  53.         for (int i = nkeys; --i >= 0;)
  54.         if (keys[i] == null)
  55.             return values[i];
  56.     } else
  57.         for (int i = nkeys; --i >= 0;)
  58.         if (k.equalsIgnoreCase(keys[i]))
  59.             return values[i];
  60.     return null;
  61.     }
  62.  
  63.     /** Find the next value that corresponds to this key.
  64.      *    It finds the first value that follows v. To iterate
  65.      *    over all the values of a key use:
  66.      *    <pre>
  67.      *        for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
  68.      *            ...
  69.      *        }
  70.      *    </pre>
  71.      */
  72.     public String findNextValue(String k, String v) {
  73.     boolean foundV = false;
  74.     if (k == null) {
  75.         for (int i = nkeys; --i >= 0;)
  76.         if (keys[i] == null)
  77.             if (foundV)
  78.             return values[i];
  79.             else if (values[i] == v)
  80.             foundV = true;
  81.     } else
  82.         for (int i = nkeys; --i >= 0;)
  83.         if (k.equalsIgnoreCase(keys[i]))
  84.             if (foundV)
  85.             return values[i];
  86.             else if (values[i] == v)
  87.             foundV = true;
  88.     return null;
  89.     }
  90.  
  91.     /** Prints the key-value pairs represented by this
  92.     header.  Also prints the RFC required blank line
  93.     at the end. Omits pairs with a null key. */
  94.     public void print(PrintStream p) {
  95.     for (int i = 0; i < nkeys; i++)
  96.         if (keys[i] != null)
  97.         p.print(keys[i] + ": " + values[i] + "\n");
  98.     p.print("\n");
  99.     }
  100.  
  101.     /** Adds a key value pair to the end of the
  102.     header.  Duplicates are allowed */
  103.     public void add(String k, String v) {
  104.     if (keys == null || nkeys >= keys.length) {
  105.         String nk[] = new String[nkeys + 4];
  106.         String nv[] = new String[nkeys + 4];
  107.         if (keys != null)
  108.         System.arraycopy(keys, 0, nk, 0, nkeys);
  109.         if (values != null)
  110.         System.arraycopy(values, 0, nv, 0, nkeys);
  111.         keys = nk;
  112.         values = nv;
  113.     }
  114.     keys[nkeys] = k;
  115.     values[nkeys] = v;
  116.     nkeys++;
  117.     }
  118.  
  119.     /** Sets the value of a key.  If the key already
  120.     exists in the header, it's value will be
  121.     changed.  Otherwise a new key/value pair will
  122.     be added to the end of the header. */
  123.     public void set(String k, String v) {
  124.     for (int i = nkeys; --i >= 0;)
  125.         if (k.equalsIgnoreCase(keys[i])) {
  126.         values[i] = v;
  127.         return;
  128.         }
  129.     add(k, v);
  130.     }
  131.  
  132.     /** Convert a message-id string to canonical form (strips off
  133.     leading and trailing <>s) */
  134.     public String canonicalID(String id) {
  135.     if (id == null)
  136.         return "";
  137.     int st = 0;
  138.     int len = id.length();
  139.     boolean substr = false;
  140.     int c;
  141.     while (st < len && ((c = id.charAt(st)) == '<' ||
  142.                 c <= ' '))
  143.         st++, substr = true;
  144.     while (st < len && ((c = id.charAt(len - 1)) == '>' ||
  145.                 c <= ' '))
  146.         len--, substr = true;
  147.     return substr ? id.substring(st, len) : id;
  148.     }
  149.  
  150.     /** Parse a MIME header from an input stream. */
  151.     public void parseHeader(InputStream is) {
  152.     nkeys = 0;
  153.     if (is == null)
  154.         return;
  155.     char s[] = new char[10];
  156.     int firstc = is.read();
  157.     while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
  158.         int len = 0;
  159.         int keyend = -1;
  160.         int c;
  161.         boolean inKey = firstc > ' ';
  162.         s[len++] = (char) firstc;
  163.     parseloop:{
  164.         while ((c = is.read()) >= 0) {
  165.             switch (c) {
  166.               case ':':
  167.             if (inKey && len > 0)
  168.                 keyend = len;
  169.             inKey = false;
  170.             break;
  171.               case '\t':
  172.             c = ' ';
  173.               case ' ':
  174.             inKey = false;
  175.             break;
  176.               case '\r':
  177.               case '\n':
  178.             firstc = is.read();
  179.             if (c == '\r' && firstc == '\n') {
  180.                 firstc = is.read();
  181.                 if (firstc == '\r')
  182.                 firstc = is.read();
  183.             }
  184.             if (firstc == '\n' || firstc == '\r' || firstc > ' ')
  185.                 break parseloop;
  186.             /* continuation */
  187.             c = ' ';
  188.             break;
  189.             }
  190.             if (len >= s.length) {
  191.             char ns[] = new char[s.length * 2];
  192.             System.arraycopy(s, 0, ns, 0, len);
  193.             s = ns;
  194.             }
  195.             s[len++] = (char) c;
  196.         }
  197.         firstc = -1;
  198.         }
  199.         while (len > 0 && s[len - 1] <= ' ')
  200.         len--;
  201.         String k;
  202.         if (keyend <= 0) {
  203.         k = null;
  204.         keyend = 0;
  205.         } else {
  206.         k = String.copyValueOf(s, 0, keyend);
  207.         if (keyend < len && s[keyend] == ':')
  208.             keyend++;
  209.         while (keyend < len && s[keyend] <= ' ')
  210.             keyend++;
  211.         }
  212.         String v;
  213.         if (keyend >= len)
  214.         v = new String();
  215.         else
  216.         v = String.copyValueOf(s, keyend, len - keyend);
  217.         add(k, v);
  218.     }
  219.     }
  220. }
  221.