001: /*****************************************************************************
002: * *
003: * This file is part of the BeanShell Java Scripting distribution. *
004: * Documentation and updates may be found at http://www.beanshell.org/ *
005: * *
006: * Sun Public License Notice: *
007: * *
008: * The contents of this file are subject to the Sun Public License Version *
009: * 1.0 (the "License"); you may not use this file except in compliance with *
010: * the License. A copy of the License is available at http://www.sun.com *
011: * *
012: * The Original Code is BeanShell. The Initial Developer of the Original *
013: * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
014: * (C) 2000. All Rights Reserved. *
015: * *
016: * GNU Public License Notice: *
017: * *
018: * Alternatively, the contents of this file may be used under the terms of *
019: * the GNU Lesser General Public License (the "LGPL"), in which case the *
020: * provisions of LGPL are applicable instead of those above. If you wish to *
021: * allow use of your version of this file only under the terms of the LGPL *
022: * and not to allow others to use your version of this file under the SPL, *
023: * indicate your decision by deleting the provisions above and replace *
024: * them with the notice and other provisions required by the LGPL. If you *
025: * do not delete the provisions above, a recipient may use your version of *
026: * this file under either the SPL or the LGPL. *
027: * *
028: * Patrick Niemeyer (pat@pat.net) *
029: * Author of Learning Java, O'Reilly & Associates *
030: * http://www.pat.net/~pat/ *
031: * *
032: *****************************************************************************/package bsh.util;
033:
034: import java.io.*;
035: import java.util.StringTokenizer;
036: import java.net.Socket;
037: import java.net.ServerSocket;
038:
039: /**
040: A very simple httpd that supports the remote server mode.
041: Files are loaded relative to the classpath (as resources).
042:
043: Warning: this is not secure! This server can probably be duped into
044: serving any file on your system! Beware!
045:
046: Note: at some point this should be recast as a beanshell script.
047: */
048: public class Httpd extends Thread {
049: ServerSocket ss;
050:
051: public static void main(String argv[]) throws IOException {
052: new Httpd(Integer.parseInt(argv[0])).start();
053: }
054:
055: public Httpd(int port) throws IOException {
056: ss = new ServerSocket(port);
057: }
058:
059: public void run() {
060: // System.out.println("starting httpd...");
061: try {
062: while (true)
063: new HttpdConnection(ss.accept()).start();
064: } catch (IOException e) {
065: System.out.println(e);
066: }
067: }
068: }
069:
070: class HttpdConnection extends Thread {
071: Socket client;
072: BufferedReader in;
073: OutputStream out;
074: PrintStream pout;
075: boolean isHttp1;
076:
077: HttpdConnection(Socket client) {
078: this .client = client;
079: setPriority(NORM_PRIORITY - 1);
080: }
081:
082: public void run() {
083: try {
084: in = new BufferedReader(new InputStreamReader(client
085: .getInputStream()));
086: out = client.getOutputStream();
087: pout = new PrintStream(out);
088:
089: String request = in.readLine();
090: if (request == null)
091: error(400, "Empty Request");
092:
093: if (request.toLowerCase().indexOf("http/1.") != -1) {
094: String s;
095: while ((!(s = in.readLine()).equals("")) && (s != null)) {
096: ;
097: }
098:
099: isHttp1 = true;
100: }
101:
102: StringTokenizer st = new StringTokenizer(request);
103: if (st.countTokens() < 2)
104: error(400, "Bad Request");
105: else {
106: String command = st.nextToken();
107: if (command.equals("GET"))
108: serveFile(st.nextToken());
109: else
110: error(400, "Bad Request");
111: }
112:
113: client.close();
114: } catch (IOException e) {
115: System.out.println("I/O error " + e);
116: try {
117: client.close();
118: } catch (Exception e2) {
119: }
120: }
121: }
122:
123: private void serveFile(String file) throws FileNotFoundException,
124: IOException {
125: // Do some mappings
126: if (file.equals("/"))
127: file = "/remote/remote.html";
128:
129: if (file.startsWith("/remote/"))
130: file = "/bsh/util/lib/" + file.substring(8);
131:
132: /*
133: if(file.startsWith("/"))
134: file = file.substring(1);
135: if(file.endsWith("/") || file.equals(""))
136: file = file + "index.html";
137:
138: if(!fileAccessOK(file))
139: {
140: error(403, "Forbidden");
141: return;
142: }
143: */
144:
145: // don't send java packages over... (e.g. swing)
146: if (file.startsWith("/java"))
147: error(404, "Object Not Found");
148: else
149: try {
150: System.out.println("sending file: " + file);
151: sendFileData(file);
152: } catch (FileNotFoundException e) {
153: error(404, "Object Not Found");
154: }
155: }
156:
157: private void sendFileData(String file) throws IOException,
158: FileNotFoundException {
159: /*
160: Why aren't resources being found when this runs on Win95?
161: */
162: InputStream fis = getClass().getResourceAsStream(file);
163: if (fis == null)
164: throw new FileNotFoundException(file);
165: byte[] data = new byte[fis.available()];
166:
167: if (isHttp1) {
168: pout.println("HTTP/1.0 200 Document follows");
169:
170: pout.println("Content-length: " + data.length);
171:
172: if (file.endsWith(".gif"))
173: pout.println("Content-type: image/gif");
174: else if (file.endsWith(".html") || file.endsWith(".htm"))
175: pout.println("Content-Type: text/html");
176: else
177: pout.println("Content-Type: application/octet-stream");
178:
179: pout.println();
180: }
181:
182: int bytesread = 0;
183: // Never, ever trust available()
184: do {
185: bytesread = fis.read(data);
186: if (bytesread > 0)
187: pout.write(data, 0, bytesread);
188: } while (bytesread != -1);
189: pout.flush();
190: }
191:
192: private void error(int num, String s) {
193: s = "<html><h1>" + s + "</h1></html>";
194: if (isHttp1) {
195: pout.println("HTTP/1.0 " + num + " " + s);
196: pout.println("Content-type: text/html");
197: pout.println("Content-length: " + s.length() + "\n");
198: }
199:
200: pout.println(s);
201: }
202: }
|