home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / net / www / protocol / http / handler.java
Text File  |  1995-08-11  |  8KB  |  290 lines

  1. /*
  2.  * @(#)Handler.java    1.28 95/05/13 James Gosling
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. /*-
  21.  *    http stream opener
  22.  */
  23.  
  24. package net.www.protocol.http;
  25.  
  26. import java.io.*;
  27. import net.www.http.*;
  28. import net.TelnetInputStream;
  29. import net.UnknownHostException;
  30. import java.util.Hashtable;
  31. import net.www.http.UnauthorizedHttpRequestException;
  32. import net.www.http.AuthenticationInfo;
  33. import net.www.html.URLStreamHandler;
  34. import net.www.html.URL;
  35. import net.www.html.MeteredStream;
  36. import net.www.auth.Authenticator;
  37. import net.ProgressData;
  38. import awt.*;
  39.  
  40. /** open an http input stream given a URL */
  41. public class Handler extends URLStreamHandler {
  42.     String    proxy;
  43.     int        proxyPort;
  44.  
  45.     public Handler() {
  46.     proxy = null;
  47.     proxyPort = -1;
  48.     }
  49.  
  50.     public Handler(String proxy, int port) {
  51.     this.proxy = proxy;
  52.     this.proxyPort = port;
  53.     }
  54.  
  55.     public InputStream openStream(URL u) {
  56.     HttpClient  http;
  57.     int        count = 0;
  58.     InputStream is = null;
  59.  
  60.     // AVH: This stuff sucks. There is a point where
  61.     // the stream is open and the InputStream is being
  62.     // returned, and an exception is thrown and the 
  63.     // stream is not closed. How do I fix this?
  64.     try {
  65.         while (true) {
  66.         if (++count >= 4) {
  67.             throw new FileNotFoundException(u.toExternalForm());
  68.         }
  69.         http = new HttpClient(u, proxy, proxyPort);
  70.         String newLocation = http.getHeaderField("location");
  71.         if (newLocation != null)
  72.             u.copy(new URL(u, newLocation));
  73.         if (http.getStatus() == HttpClient.OK || newLocation == null)
  74.             break;
  75.         http.closeServer();
  76.         if (!"http".equals(u.protocol))
  77.             return u.openStream();    /* redirecting to some protocol other than http */
  78.         }
  79.         is = http.getInputStream();
  80.         u.setType(getContentType(http, u));
  81.  
  82.         /*
  83.          * If the http stream returns a content-length attribute we
  84.          * wrap a MeteredStream around the network stream so we get
  85.          * some feedback about the progress of the connection.
  86.          */
  87.         String ct = http.getHeaderField("content-length");
  88.         int len = 0;
  89.         if (ct != null && (len = Integer.parseInt(ct)) != 0) {
  90.         is = new MeteredStream(is, len, u);
  91.         } else {
  92.         ProgressData.pdata.unregister(u);
  93.         }
  94.         return is;
  95.     } catch (Object e) {
  96.         if (is != null) {
  97.         is.close();
  98.         }
  99.         ProgressData.pdata.unregister(u);
  100.         throw e;
  101.     }
  102.     }
  103.  
  104.     static AuthorizationDialog    dialog = null;
  105.  
  106.     private static AuthenticationInfo getAuthentication(URL url, String scheme, String realm) {
  107.     Authenticator    auth;
  108.     OutputStreamBuffer  out = new OutputStreamBuffer(64);
  109.     AuthenticationInfo  info;
  110.  
  111.     // always convert the scheme to lower case so we get a consistent 
  112.     // class name.
  113.     auth = (Authenticator) new("net.www.auth." + scheme.toLowerCase());
  114.     if (dialog == null) {
  115.         dialog = new AuthorizationDialog();
  116.     }
  117.     String    userAndPassword = dialog.getAuth(url, realm);
  118.  
  119.     if (userAndPassword == null) {
  120.         return null;
  121.     }
  122.     auth.encrypt(new InputStreamStringBuffer(userAndPassword), out);
  123.     info = new AuthenticationInfo(url.host, url.getPort(), realm,
  124.                       scheme + " " + out.toString());
  125.     return info;
  126.     }
  127.  
  128.     /**
  129.      * Similar to openStream except that it will pop up a dialog box to
  130.      * resolve authentication failures.     */
  131.     public InputStream openStreamInteractively(URL u) {
  132.     AuthenticationInfo  info = null;
  133.  
  134.     while (true) {
  135.         try {
  136.         InputStream is = openStream(u);
  137.         return is;
  138.         } catch (UnauthorizedHttpRequestException e) {
  139.         HttpClient http = e.http;
  140.         try {
  141.             String  scheme = http.getAuthenticationScheme();
  142.             String  realm = http.getAuthenticationRealm();
  143.  
  144.             info = getAuthentication(u, scheme, realm);
  145.             if (info == null) {
  146.             u.setType(getContentType(http, u));
  147.             return http.getInputStream();
  148.             }
  149.             http.closeServer();
  150.             continue;
  151.         } catch (Exception e1) {
  152.             http.closeServer();
  153.             throw e1;
  154.         }
  155.         }
  156.     }
  157.     }
  158.  
  159.  
  160.     private String getContentType(HttpClient http, URL u) {
  161.     String ct = http.getHeaderField("content-type");
  162.     String ce = http.getHeaderField("content-encoding");
  163.  
  164.     if (ct == null || (ct = u.mimeToContent(ct)) == null) {
  165.         if (u.file.endsWith("/")) {
  166.         ct = URL.content_html;
  167.         } else {
  168.         ct = formatFromName(u.file);
  169.         }
  170.     }
  171.     /*
  172.      * If the Mime header had a Content-encoding field and its
  173.      * value was not one of the values that essentially indicate
  174.      * no encoding, we force the content type to be unknown.
  175.      * This will cause a save dialog to be presented to the
  176.      * user.  It is not ideal but is better than what we were
  177.      * previously doing, namely bringing up an image tool for
  178.      * compressed tar files.
  179.      */
  180.  
  181.     if (ce != null && 
  182.            !(ce.equalsIgnoreCase("7bit") 
  183.          || ce.equalsIgnoreCase("8bit") 
  184.          || ce.equalsIgnoreCase("binary"))) {
  185.         ct = URL.content_unknown;
  186.     }
  187.  
  188.     return ct;
  189.     }
  190. }
  191.  
  192. class AuthorizationDialog extends Frame {
  193.     TextField    passwordField;
  194.     TextField    userField;
  195. //    Label    mainLabel;
  196.     Window    cw;
  197.     Window    sw;
  198.  
  199.     String    auth;
  200.     boolean    authSet;
  201.  
  202.     public AuthorizationDialog() {
  203.     super(true, 300, 150, Color.lightGray);
  204.     setDefaultFont(wServer.fonts.getFont("Dialog", Font.BOLD, 12));
  205.  
  206.     Label l;
  207.  
  208. //    mainLabel = new Label("", null, cw, null);
  209. //    mainLabel.setHFill(true);
  210.  
  211.     cw = new Window(this,"Center", background, 300, 100);
  212.     cw.setLayout(new RowColLayout(0, 2, true));
  213.  
  214.     Column col = new Column(cw, null, false);
  215.  
  216.     new Space(col, null, 12, 5, false, false);
  217.     l = new Label("User:",null, col, null);
  218.     userField = new TextField("","",cw, true);
  219.  
  220.     col = new Column(cw, null, false);    
  221.     new Space(col, null, 12, 5, false, false);
  222.     l = new Label("Password:",null, col, null);
  223.  
  224.     passwordField = new TextField("","",cw, true);
  225.     passwordField.setEchoCharacter('#');
  226.  
  227.     sw = new Window(this, "South", background, 100, 30);
  228.     sw.setLayout(new RowLayout(true));
  229.     new FrameButton("Login", sw, this);
  230.     new FrameButton("Clear", sw, this);
  231.     new FrameButton("Cancel", sw, this);
  232.     }
  233.  
  234.     int    preferredHeight = 151;
  235.  
  236.     public synchronized String getAuth(URL url, String realm) {
  237.     String    title = "Login to " + realm + " at " + url.host;
  238.     int width = cw.getFontMetrics(defaultFont).stringWidth(title);
  239.  
  240.     setTitle(title);
  241.     authSet = false;
  242.     reshape(x, y, width + 80, preferredHeight);
  243.     resize();
  244.     map();
  245.     while (!authSet)
  246.         wait();
  247.     return auth;
  248.     }
  249.  
  250.     public void map() {
  251.     userField.setText("");
  252.     passwordField.setText("");
  253.     super.map();
  254.     }    
  255.  
  256.     private synchronized void setAuth(String auth) {
  257.     this.auth = auth;
  258.     authSet = true;
  259.     notifyAll();
  260.     }
  261.  
  262.     public void handleButtonClick(Button b) {
  263.     String    label = b.label;
  264.  
  265.     if (label.equals("Login")) {
  266.         setAuth(userField.getText() + ":" + passwordField.getText());
  267.         unMap();
  268.     } else if (label.equals("Clear")) {
  269.         userField.setText("");
  270.         passwordField.setText("");
  271.     } else {
  272.         setAuth(null);
  273.         unMap();
  274.     }
  275.     }
  276. }
  277.  
  278. class FrameButton extends Button {
  279.     AuthorizationDialog    owner;
  280.  
  281.     public FrameButton(String name, Container cw, AuthorizationDialog d) {
  282.     super(name, "", cw);
  283.     owner = d;
  284.     }
  285.  
  286.     public void selected(Component c, int pos) {
  287.     owner.handleButtonClick(this);
  288.     }
  289. }
  290.