ContentMD5Module.java
上传用户:demmber
上传日期:2007-12-22
资源大小:717k
文件大小:4k
源码类别:

Java编程

开发平台:

Java

  1. /*
  2.  * @(#)ContentMD5Module.java 0.3-3 06/05/2001
  3.  *
  4.  *  This file is part of the HTTPClient package
  5.  *  Copyright (C) 1996-2001 Ronald Tschal鋜
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Lesser General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Lesser General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU Lesser General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20.  *  MA 02111-1307, USA
  21.  *
  22.  *  For questions, suggestions, bug-reports, enhancement-requests etc.
  23.  *  I may be contacted at:
  24.  *
  25.  *  ronald@innovation.ch
  26.  *
  27.  *  The HTTPClient's home page is located at:
  28.  *
  29.  *  http://www.innovation.ch/java/HTTPClient/ 
  30.  *
  31.  */
  32. package HTTPClient;
  33. import java.io.IOException;
  34. /**
  35.  * This module handles the Content-MD5 response header. If this header was
  36.  * sent with a response and the entity isn't encoded using an unknown
  37.  * transport encoding then an MD5InputStream is wrapped around the response
  38.  * input stream. The MD5InputStream keeps a running digest and checks this
  39.  * against the expected digest from the Content-MD5 header the stream is
  40.  * closed. An IOException is thrown at that point if the digests don't match.
  41.  *
  42.  * @version 0.3-3  06/05/2001
  43.  * @author Ronald Tschal鋜
  44.  */
  45. class ContentMD5Module implements HTTPClientModule
  46. {
  47.     // Constructors
  48.     ContentMD5Module()
  49.     {
  50.     }
  51.     // Methods
  52.     /**
  53.      * Invoked by the HTTPClient.
  54.      */
  55.     public int requestHandler(Request req, Response[] resp)
  56.     {
  57. return REQ_CONTINUE;
  58.     }
  59.     /**
  60.      * Invoked by the HTTPClient.
  61.      */
  62.     public void responsePhase1Handler(Response resp, RoRequest req)
  63.     {
  64.     }
  65.     /**
  66.      * Invoked by the HTTPClient.
  67.      */
  68.     public int responsePhase2Handler(Response resp, Request req)
  69.     {
  70. return RSP_CONTINUE;
  71.     }
  72.     /**
  73.      * Invoked by the HTTPClient.
  74.      */
  75.     public void responsePhase3Handler(Response resp, RoRequest req)
  76. throws IOException, ModuleException
  77.     {
  78. if (req.getMethod().equals("HEAD"))
  79.     return;
  80. String md5_digest = resp.getHeader("Content-MD5");
  81. String trailer    = resp.getHeader("Trailer");
  82. boolean md5_tok = false;
  83. try
  84. {
  85.     if (trailer != null)
  86. md5_tok = Util.hasToken(trailer, "Content-MD5");
  87. }
  88. catch (ParseException pe)
  89.     { throw new ModuleException(pe.toString()); }
  90. if ((md5_digest == null  &&  !md5_tok)  ||
  91.     resp.getHeader("Transfer-Encoding") != null)
  92.     return;
  93. if (md5_digest != null)
  94.     Log.write(Log.MODS, "CMD5M: Received digest: " + md5_digest +
  95. " - pushing md5-check-stream");
  96. else
  97.     Log.write(Log.MODS, "CMD5M: Expecting digest in trailer " +
  98. " - pushing md5-check-stream");
  99. resp.inp_stream = new MD5InputStream(resp.inp_stream,
  100.      new VerifyMD5(resp));
  101.     }
  102.     /**
  103.      * Invoked by the HTTPClient.
  104.      */
  105.     public void trailerHandler(Response resp, RoRequest req)
  106.     {
  107.     }
  108. }
  109. class VerifyMD5 implements HashVerifier
  110. {
  111.     RoResponse resp;
  112.     public VerifyMD5(RoResponse resp)
  113.     {
  114. this.resp = resp;
  115.     }
  116.     public void verifyHash(byte[] hash, long len)  throws IOException
  117.     {
  118. String hdr;
  119. try
  120. {
  121.     if ((hdr = resp.getHeader("Content-MD5")) == null)
  122. hdr = resp.getTrailer("Content-MD5");
  123. }
  124. catch (IOException ioe)
  125.     { return; } // shouldn't happen
  126. if (hdr == null)  return;
  127. byte[] ContMD5 = Codecs.base64Decode(hdr.trim().getBytes("8859_1"));
  128. for (int idx=0; idx<hash.length; idx++)
  129. {
  130.     if (hash[idx] != ContMD5[idx])
  131. throw new IOException("MD5-Digest mismatch: expected " +
  132.       hex(ContMD5) + " but calculated " +
  133.       hex(hash));
  134. }
  135. Log.write(Log.MODS, "CMD5M: hash successfully verified");
  136.     }
  137.     /**
  138.      * Produce a string of the form "A5:22:F1:0B:53"
  139.      */
  140.     private static String hex(byte[] buf)
  141.     {
  142. StringBuffer str = new StringBuffer(buf.length*3);
  143. for (int idx=0; idx<buf.length; idx++)
  144. {
  145.     str.append(Character.forDigit((buf[idx] >>> 4) & 15, 16));
  146.     str.append(Character.forDigit(buf[idx] & 15, 16));
  147.     str.append(':');
  148. }
  149. str.setLength(str.length()-1);
  150. return str.toString();
  151.     }
  152. }