/*
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public final class HttpServer extends Thread
{
	static final boolean DEBUG = false;
	static final boolean _monitorEnable = true;

//	static final String _DocumentRoot = "/wwwRoot";	// directory
	static final String _DocumentRoot = "www";	// directory
	static final int _Listen = 80;	// port
	static final String _DirectoryIndex = "index.html";

	static final String _ErrorDocument403 = "<html><body>403 Forbidden</body></html>";
	static final String _ErrorDocument404 = "<html><body>404 Not Found</body></html>";

	Socket _socket;

	public HttpServer(Socket socket)
	{
		_socket = socket;
		start();
	}
	
	public static void main(String[] args)
	{
		System.out.print("[httpd] DocumentRoot=" + new File(_DocumentRoot).getAbsolutePath() + "\n");
		System.out.print("[httpd] Listen=" + _Listen + "\n");
		try
		{
			ServerSocket ss = new ServerSocket(_Listen);
			for (;;)
			{
				new HttpServer(ss.accept());
			}
		}
		catch (Exception e)
		{
		}
		System.out.println("[httpd] stop");
	}
	
	public void run()
	{
		try
		{
			BufferedReader is = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
			String cmdGET = null;
//			String cmdAccept = null;
//			String cmdUserAgent = null;
//			String cmdHost = null;
//			String cmdConnection = null;
//			String cmdCacheControl = null;
			String cmd;
			while ((cmd = is.readLine()).length() > 0)
			{
				if (DEBUG)
					System.out.println("[DEBUG] < " + cmd);
				if (cmd.startsWith("GET"))
					cmdGET = cmd;
			}
			if (cmdGET != null)
			{
				if (_monitorEnable)
					System.out.print("[httpd] "+_socket.getInetAddress().getHostAddress()+" - \"" + cmdGET + "\" ");
				DataOutputStream os = new DataOutputStream(_socket.getOutputStream());

				String path = cmdGET.split(" ")[1];
				String query = null;

				if (path.charAt(0) != '/'
				 || path.indexOf("/.") >= 0
				 || path.indexOf("..") >= 0)
				{
					if (_monitorEnable)
						System.out.println("403 FORBIDDEN");
					os.writeBytes("HTTP/1.0 403 FORBIDDEN\n\n");
					os.writeBytes(_ErrorDocument403);
					return;
				}

				int ix = path.indexOf('?');
				if (ix > 0) {
					query = path.substring(ix);
					path  = path.substring(0, ix);
				}

				StringBuilder sb = new StringBuilder(path.length() + 32)
						.append(_DocumentRoot).append(path);
				if (path.endsWith("/"))
					sb.append(_DirectoryIndex);
				path = sb.toString();
				sb = null;

				File file = new File(path);
				int length = (int)file.length();
				try {
					byte[] buffer = new byte[length > 32768 ? 32768 : length];
					FileInputStream fi = new FileInputStream(file);
					os.writeBytes("HTTP/1.0 200 OK\nContent-Length:" + length + "\n\n");
					int n;
					while ((n = fi.read(buffer)) > 0)
						os.write(buffer, 0, n);
					if (_monitorEnable)
						System.out.println("200 " + length);
					if (DEBUG)
						System.out.println("[DEBUG] > " + file.getAbsolutePath());
				}
				catch (IOException e)
				{
					if (_monitorEnable)
						System.out.println("404 NOT FOUND");
					os.writeBytes("HTTP/1.0 404 Not Found\n\n");
					os.writeBytes(_ErrorDocument404);
				}
				os.close();
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}
