Connection.java
上传用户:huihesys
上传日期:2007-01-04
资源大小:3877k
文件大小:10k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /* $Id: Connection.java,v 1.5 2000/04/18 13:13:24 wastl Exp $ */
  2. package net.wastl.webmail.standalone;
  3. import java.io.*;
  4. import java.net.*;
  5. import java.util.*;
  6. import java_cup.runtime.*;
  7. import net.wastl.webmail.server.http.*;
  8. import net.wastl.webmail.ui.*;
  9. import net.wastl.webmail.ui.html.*;
  10. import net.wastl.webmail.server.*;
  11. import net.wastl.webmail.debug.ErrorHandler;
  12. /**
  13.  * Connection.java
  14.  *
  15.  * Created: Tue Feb  2 12:41:59 1999
  16.  *
  17.  * Copyright (C) 1999-2000 Sebastian Schaffert
  18.  * 
  19.  * This program is free software; you can redistribute it and/or
  20.  * modify it under the terms of the GNU General Public License
  21.  * as published by the Free Software Foundation; either version 2
  22.  * of the License, or (at your option) any later version.
  23.  * 
  24.  * This program is distributed in the hope that it will be useful,
  25.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  * GNU General Public License for more details.
  28.  * 
  29.  * You should have received a copy of the GNU General Public License
  30.  * along with this program; if not, write to the Free Software
  31.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  32.  */
  33. /**
  34.  *
  35.  *
  36.  *
  37.  * @author Sebastian Schaffert
  38.  * @version $Revision: 1.5 $
  39.  */
  40. public class Connection extends Thread implements TimeableConnection {
  41.     private long last_access;
  42.     private Reader in;
  43.     private PrintWriter out;
  44.     
  45.     private HTTPRequestHeader http_header;
  46.     private ConnectionTimer vulture;
  47.     
  48.     private Socket sock;
  49.     private long timeout;
  50.     
  51.     private WebMailServer parent;
  52.     private HTTPSession sess;
  53.     private HTTPServer http_server;
  54.     private HTTPParser parser;
  55.     private static long connections=0;
  56.     private boolean keep_alive=true;
  57.     private boolean stop=false;
  58.     /** Size of the chunks that are sent. Must not be greater than 65536 */
  59.     private static final int chunk_size=8192;
  60.     public Connection(Socket sock,WebMailServer parent, HTTPServer http_server) {
  61. super(http_server.getThreadGroup(),"Connection-"+(connections++)+" to "+sock.getInetAddress().getHostName());
  62. http_server.lockConnection();
  63. this.parent=parent;
  64. this.http_server=http_server;
  65. this.sock=sock;
  66. this.vulture=parent.getConnectionTimer();
  67. try {
  68.     timeout=Long.parseLong(WebMailServer.getStorage().getConfig("http timeout"));
  69. } catch(NumberFormatException ex) {
  70.     timeout=60000;
  71. }
  72. vulture.addTimeableConnection(this);
  73. last_access=System.currentTimeMillis();
  74. try {
  75.     sock.setSoTimeout((int)timeout);
  76.     last_access=System.currentTimeMillis();
  77.     this.start();
  78. } catch(IOException ex) {
  79.     new ErrorHandler(ex);
  80. }
  81.     }
  82.     
  83.     private HTTPRequestHeader getHTTPRequestHeader() {
  84. return http_header;
  85.     }
  86.    /* Send CONTINUE response to >= HTTP/1.1 clients */  
  87.    public void checkVersion(String version) {
  88.         try {
  89.           double v=Double.valueOf(version).doubleValue();
  90.           if(v>=1.1) {
  91.             out.print("HTTP/1.1 100 Continuernrn");
  92.   }
  93.         } catch(NumberFormatException e) {
  94.           e.printStackTrace();
  95. }
  96.     }
  97.     public void run() {
  98. HTTPResponseHeader r;
  99. HTMLDocument content=null;
  100.         int err_code=400;
  101. try {
  102.     out=new PrintWriter(sock.getOutputStream());     
  103.     in=new InputStreamReader(sock.getInputStream());
  104.     int loops=0;
  105.             while(keep_alive && !isInterrupted() && !stop) {
  106. loops++;
  107. last_access=System.currentTimeMillis();
  108. // This section uses the new HTTPParser and Lexer
  109. http_header=new HTTPRequestHeader();
  110. parser=new HTTPParser(in,this,http_header);
  111. //long m_s=System.currentTimeMillis();
  112. parser.parse();
  113. //long m_e=System.currentTimeMillis();
  114. //System.err.println("Parsing took "+(m_e-m_s)+" ms");
  115. // End Parser section
  116. if(stop) {
  117.     throw new InterruptedException("Interrupted");
  118. }
  119. StringTokenizer tok=new StringTokenizer(http_header.getPath(),"?");
  120. String url=tok.nextToken();
  121. if(tok.hasMoreTokens()) {
  122.     http_header.setEncodedContent(http_header.getPath().substring(url.length()+1),"application/x-www-form-urlencoded");
  123. }
  124. //System.err.println(http_header);
  125. last_access=System.currentTimeMillis();
  126. if(loops==1) {
  127.     parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "+
  128.     sock.getInetAddress().toString()+
  129.     " established (Thread '"+this.getName()+
  130.     "'). Remote wants ""+http_header.getPath()+"".");
  131. } else {
  132.     parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "
  133.     +sock.getInetAddress().toString()+
  134.     " (Thread '"+this.getName()+"' loop "+loops+
  135.     "). Remote wants ""+http_header.getPath()+"".");
  136. }
  137. if(!http_header.getMethod().toUpperCase().equals("GET") &&
  138.    !http_header.getMethod().toUpperCase().equals("HEAD") &&
  139.    !http_header.getMethod().toUpperCase().equals("POST")) {
  140.     err_code=404;
  141.     throw new DocumentNotFoundException("Method not allowed");
  142. } else if(http_header.getMethod().toUpperCase().equals("POST") &&
  143.   (http_header.getHeader("Content-length")==null || http_header.getHeader("Content-length").equals(""))) { 
  144.     err_code=411;
  145.     throw new DocumentNotFoundException("No Content-Length given");
  146. }
  147. try {
  148.     /* Find out about the session id */
  149.     if(url.startsWith("/SESS")) {
  150. StringTokenizer t=new StringTokenizer(http_header.getPath(),"-/");
  151. t.nextToken();
  152. String sessionid=t.nextToken();
  153. sess=parent.getSession(sessionid,sock.getInetAddress(),http_header);
  154. /* "/SESS-" = 6 characters plus length of sessionid */
  155. url=http_header.getPath().substring(sessionid.length()+6);
  156.     } else if(http_header.getContent("session-id")!=null) {
  157. sess=parent.getSession(http_header.getContent("session-id"),sock.getInetAddress(),http_header);
  158.     } else if(url.startsWith("/login")) {
  159. sess=parent.newSession(sock.getInetAddress(),http_header);
  160.     } else if(url.startsWith("/admin/login")) {
  161. http_header.setHeader("LOGIN","Administrator");
  162. System.err.println("Generating new admin session ...");
  163. sess=parent.newAdminSession(sock.getInetAddress(),http_header);
  164. System.err.println("done.");
  165.     }
  166.     /* Let the URLHandler determine the document to use */
  167.     content=parent.getURLHandler().handleURL(url,sess,http_header);
  168. } catch(InvalidPasswordException e) {
  169.     parent.getStorage().log(Storage.LOG_ERR,"Connection to "+sock.getInetAddress().toString()+
  170.     ": Authentication failed!");
  171.     if(url.startsWith("/admin/login")) {
  172. content=parent.getURLHandler().handleURL("/admin",null,http_header);
  173.     } else if(url.startsWith("/login")) {
  174. content=parent.getURLHandler().handleURL("/",null,http_header);
  175.     } else {
  176. content=new HTMLErrorMessage(parent.getStorage(),e.getMessage());
  177.     }
  178. } catch(InvalidDataException ex) {
  179.     content=new HTMLErrorMessage(parent.getStorage(),ex.getMessage());
  180. } catch(Exception ex) {
  181.     ex.printStackTrace();
  182. }
  183. synchronized(out) {
  184.     r=new HTTPResponseHeader(content.getReturnCode(),content.getReturnStatus());
  185.     if(content.hasHTTPHeader()) {
  186. Enumeration enum=content.getHTTPHeaderKeys();
  187. while(enum.hasMoreElements()) {
  188.     String s=(String)enum.nextElement();
  189.     r.putHeader(s,content.getHTTPHeader(s));
  190. }
  191.     }
  192.     
  193.     if(content instanceof HTMLImage) {
  194. HTMLImage img=(HTMLImage)content;
  195. r.putHeader("Content-Type",img.getContentType());
  196. r.putHeader("Content-Transfer-Encoding",img.getContentEncoding());
  197. r.putHeader("Content-Length",""+img.size());
  198. r.putHeader("Connection","Keep-Alive");
  199. out.print(r.toString());
  200. out.flush();
  201. sock.getOutputStream().flush();
  202. BufferedOutputStream iout=new BufferedOutputStream(sock.getOutputStream());
  203. /* Send 8k junks */
  204. int offset=0;
  205. while(offset + chunk_size < img.size()) {
  206.     iout.write(img.toBinary(),offset,chunk_size);
  207.     offset+=chunk_size;
  208. }
  209. iout.write(img.toBinary(),offset,img.size()-offset);
  210. iout.flush();
  211. sock.getOutputStream().flush();
  212. if(http_header.getHeader("Connection")==null || 
  213.    !http_header.getHeader("Connection").toUpperCase().equals("KEEP-ALIVE")) {
  214.     keep_alive=false;
  215.     sock.getOutputStream().close();
  216. }
  217.     } else {
  218. r.putHeader("Content-Length",""+(content.length()+11));
  219. r.putHeader("Connection","Keep-Alive");
  220. r.putHeader("Content-Type","text/html");
  221. out.print(r.toString());
  222. //System.err.println(r.toString());
  223. out.print(content+"rn");
  224. out.print("</HTML>rn");
  225. out.flush();
  226. if(!http_header.getVersion().equals("1.1") && 
  227.    (http_header.getHeader("Connection")==null || 
  228.     !http_header.getHeader("Connection").toUpperCase().equals("KEEP-ALIVE"))) {
  229.     keep_alive=false;
  230.     out.close();
  231. }
  232.     }
  233. }
  234.             }
  235. } catch(DocumentNotFoundException e) {
  236.     parent.getStorage().log(Storage.LOG_INFO,"Connection to "+sock.getInetAddress().toString()+
  237.   ": Could not handle request ("+err_code+") (Reason: "+e.getMessage()+")");
  238.     r=new HTTPResponseHeader(err_code,"Could not handle request");
  239.     r.putHeader("Content-type","text/html");
  240.             r.putHeader("Connection","close");
  241.     
  242.     content=new HTMLErrorMessage(WebMailServer.getStorage(),e.getMessage());
  243.     out.print(r.toString());
  244.     out.print(content+"rn");
  245.     out.print("</HTML>rn");
  246.     out.flush();
  247.     out.close();
  248. } catch(Exception e) {
  249.   parent.getStorage().log(Storage.LOG_INFO,"Connection to "+sock.getInetAddress().toString()+" (Thread '"+this.getName()+"') interrupted.");
  250. }
  251. this.close();
  252.     }
  253.     public long getLastAccess() {
  254. return last_access;
  255.     }
  256.     private void close() {
  257. try {
  258.     http_server.unlockConnection();
  259.     sock.close();
  260. } catch(IOException ex) {
  261.     ex.printStackTrace();
  262. } finally {
  263.     parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "+sock.getInetAddress().toString()+" closed.");
  264.     vulture.removeTimeableConnection(this);
  265. }
  266.     }
  267.     public void timeoutOccured() {
  268. parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "+sock.getInetAddress().toString()+": Timeout.");
  269. stop=true;
  270. this.interrupt();
  271. parser.done_parsing();
  272. this.close();
  273.     }
  274.  
  275.     public long getTimeout() {
  276. return timeout;
  277.     }
  278. } // Connection