Connection.java
上传用户:huihesys
上传日期:2007-01-04
资源大小:3877k
文件大小:10k
- /* $Id: Connection.java,v 1.5 2000/04/18 13:13:24 wastl Exp $ */
- package net.wastl.webmail.standalone;
- import java.io.*;
- import java.net.*;
- import java.util.*;
- import java_cup.runtime.*;
- import net.wastl.webmail.server.http.*;
- import net.wastl.webmail.ui.*;
- import net.wastl.webmail.ui.html.*;
- import net.wastl.webmail.server.*;
- import net.wastl.webmail.debug.ErrorHandler;
- /**
- * Connection.java
- *
- * Created: Tue Feb 2 12:41:59 1999
- *
- * Copyright (C) 1999-2000 Sebastian Schaffert
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- /**
- *
- *
- *
- * @author Sebastian Schaffert
- * @version $Revision: 1.5 $
- */
- public class Connection extends Thread implements TimeableConnection {
- private long last_access;
- private Reader in;
- private PrintWriter out;
-
- private HTTPRequestHeader http_header;
- private ConnectionTimer vulture;
-
- private Socket sock;
- private long timeout;
-
- private WebMailServer parent;
- private HTTPSession sess;
- private HTTPServer http_server;
- private HTTPParser parser;
- private static long connections=0;
- private boolean keep_alive=true;
- private boolean stop=false;
- /** Size of the chunks that are sent. Must not be greater than 65536 */
- private static final int chunk_size=8192;
- public Connection(Socket sock,WebMailServer parent, HTTPServer http_server) {
- super(http_server.getThreadGroup(),"Connection-"+(connections++)+" to "+sock.getInetAddress().getHostName());
- http_server.lockConnection();
- this.parent=parent;
- this.http_server=http_server;
- this.sock=sock;
- this.vulture=parent.getConnectionTimer();
- try {
- timeout=Long.parseLong(WebMailServer.getStorage().getConfig("http timeout"));
- } catch(NumberFormatException ex) {
- timeout=60000;
- }
- vulture.addTimeableConnection(this);
- last_access=System.currentTimeMillis();
- try {
- sock.setSoTimeout((int)timeout);
- last_access=System.currentTimeMillis();
- this.start();
- } catch(IOException ex) {
- new ErrorHandler(ex);
- }
- }
-
- private HTTPRequestHeader getHTTPRequestHeader() {
- return http_header;
- }
- /* Send CONTINUE response to >= HTTP/1.1 clients */
- public void checkVersion(String version) {
- try {
- double v=Double.valueOf(version).doubleValue();
- if(v>=1.1) {
- out.print("HTTP/1.1 100 Continuernrn");
- }
- } catch(NumberFormatException e) {
- e.printStackTrace();
- }
- }
- public void run() {
- HTTPResponseHeader r;
- HTMLDocument content=null;
- int err_code=400;
- try {
- out=new PrintWriter(sock.getOutputStream());
- in=new InputStreamReader(sock.getInputStream());
- int loops=0;
- while(keep_alive && !isInterrupted() && !stop) {
- loops++;
- last_access=System.currentTimeMillis();
- // This section uses the new HTTPParser and Lexer
- http_header=new HTTPRequestHeader();
- parser=new HTTPParser(in,this,http_header);
-
- //long m_s=System.currentTimeMillis();
- parser.parse();
- //long m_e=System.currentTimeMillis();
- //System.err.println("Parsing took "+(m_e-m_s)+" ms");
- // End Parser section
-
- if(stop) {
- throw new InterruptedException("Interrupted");
- }
- StringTokenizer tok=new StringTokenizer(http_header.getPath(),"?");
- String url=tok.nextToken();
- if(tok.hasMoreTokens()) {
- http_header.setEncodedContent(http_header.getPath().substring(url.length()+1),"application/x-www-form-urlencoded");
- }
- //System.err.println(http_header);
- last_access=System.currentTimeMillis();
-
- if(loops==1) {
- parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "+
- sock.getInetAddress().toString()+
- " established (Thread '"+this.getName()+
- "'). Remote wants ""+http_header.getPath()+"".");
- } else {
- parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "
- +sock.getInetAddress().toString()+
- " (Thread '"+this.getName()+"' loop "+loops+
- "). Remote wants ""+http_header.getPath()+"".");
- }
-
- if(!http_header.getMethod().toUpperCase().equals("GET") &&
- !http_header.getMethod().toUpperCase().equals("HEAD") &&
- !http_header.getMethod().toUpperCase().equals("POST")) {
- err_code=404;
- throw new DocumentNotFoundException("Method not allowed");
- } else if(http_header.getMethod().toUpperCase().equals("POST") &&
- (http_header.getHeader("Content-length")==null || http_header.getHeader("Content-length").equals(""))) {
- err_code=411;
- throw new DocumentNotFoundException("No Content-Length given");
- }
-
- try {
- /* Find out about the session id */
- if(url.startsWith("/SESS")) {
- StringTokenizer t=new StringTokenizer(http_header.getPath(),"-/");
- t.nextToken();
- String sessionid=t.nextToken();
- sess=parent.getSession(sessionid,sock.getInetAddress(),http_header);
- /* "/SESS-" = 6 characters plus length of sessionid */
- url=http_header.getPath().substring(sessionid.length()+6);
- } else if(http_header.getContent("session-id")!=null) {
- sess=parent.getSession(http_header.getContent("session-id"),sock.getInetAddress(),http_header);
- } else if(url.startsWith("/login")) {
- sess=parent.newSession(sock.getInetAddress(),http_header);
- } else if(url.startsWith("/admin/login")) {
- http_header.setHeader("LOGIN","Administrator");
- System.err.println("Generating new admin session ...");
- sess=parent.newAdminSession(sock.getInetAddress(),http_header);
- System.err.println("done.");
- }
- /* Let the URLHandler determine the document to use */
- content=parent.getURLHandler().handleURL(url,sess,http_header);
- } catch(InvalidPasswordException e) {
- parent.getStorage().log(Storage.LOG_ERR,"Connection to "+sock.getInetAddress().toString()+
- ": Authentication failed!");
- if(url.startsWith("/admin/login")) {
- content=parent.getURLHandler().handleURL("/admin",null,http_header);
- } else if(url.startsWith("/login")) {
- content=parent.getURLHandler().handleURL("/",null,http_header);
- } else {
- content=new HTMLErrorMessage(parent.getStorage(),e.getMessage());
- }
- } catch(InvalidDataException ex) {
- content=new HTMLErrorMessage(parent.getStorage(),ex.getMessage());
- } catch(Exception ex) {
- ex.printStackTrace();
- }
-
- synchronized(out) {
- r=new HTTPResponseHeader(content.getReturnCode(),content.getReturnStatus());
- if(content.hasHTTPHeader()) {
- Enumeration enum=content.getHTTPHeaderKeys();
- while(enum.hasMoreElements()) {
- String s=(String)enum.nextElement();
- r.putHeader(s,content.getHTTPHeader(s));
- }
- }
-
- if(content instanceof HTMLImage) {
- HTMLImage img=(HTMLImage)content;
- r.putHeader("Content-Type",img.getContentType());
- r.putHeader("Content-Transfer-Encoding",img.getContentEncoding());
- r.putHeader("Content-Length",""+img.size());
- r.putHeader("Connection","Keep-Alive");
- out.print(r.toString());
- out.flush();
- sock.getOutputStream().flush();
- BufferedOutputStream iout=new BufferedOutputStream(sock.getOutputStream());
-
- /* Send 8k junks */
- int offset=0;
- while(offset + chunk_size < img.size()) {
- iout.write(img.toBinary(),offset,chunk_size);
- offset+=chunk_size;
- }
- iout.write(img.toBinary(),offset,img.size()-offset);
- iout.flush();
-
- sock.getOutputStream().flush();
- if(http_header.getHeader("Connection")==null ||
- !http_header.getHeader("Connection").toUpperCase().equals("KEEP-ALIVE")) {
- keep_alive=false;
- sock.getOutputStream().close();
- }
- } else {
- r.putHeader("Content-Length",""+(content.length()+11));
- r.putHeader("Connection","Keep-Alive");
- r.putHeader("Content-Type","text/html");
- out.print(r.toString());
- //System.err.println(r.toString());
- out.print(content+"rn");
- out.print("</HTML>rn");
- out.flush();
- if(!http_header.getVersion().equals("1.1") &&
- (http_header.getHeader("Connection")==null ||
- !http_header.getHeader("Connection").toUpperCase().equals("KEEP-ALIVE"))) {
- keep_alive=false;
- out.close();
- }
- }
- }
- }
- } catch(DocumentNotFoundException e) {
- parent.getStorage().log(Storage.LOG_INFO,"Connection to "+sock.getInetAddress().toString()+
- ": Could not handle request ("+err_code+") (Reason: "+e.getMessage()+")");
- r=new HTTPResponseHeader(err_code,"Could not handle request");
- r.putHeader("Content-type","text/html");
- r.putHeader("Connection","close");
-
- content=new HTMLErrorMessage(WebMailServer.getStorage(),e.getMessage());
- out.print(r.toString());
- out.print(content+"rn");
- out.print("</HTML>rn");
- out.flush();
- out.close();
- } catch(Exception e) {
- parent.getStorage().log(Storage.LOG_INFO,"Connection to "+sock.getInetAddress().toString()+" (Thread '"+this.getName()+"') interrupted.");
- }
- this.close();
- }
- public long getLastAccess() {
- return last_access;
- }
- private void close() {
- try {
- http_server.unlockConnection();
- sock.close();
- } catch(IOException ex) {
- ex.printStackTrace();
- } finally {
- parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "+sock.getInetAddress().toString()+" closed.");
- vulture.removeTimeableConnection(this);
- }
- }
- public void timeoutOccured() {
- parent.getStorage().log(Storage.LOG_INFO,"HTTP: Connection to "+sock.getInetAddress().toString()+": Timeout.");
- stop=true;
- this.interrupt();
- parser.done_parsing();
- this.close();
- }
-
- public long getTimeout() {
- return timeout;
- }
- } // Connection