#!/usr/bin/env python

# Copyright (C) 2004,2005 PreludeIDS Technologies. All Rights Reserved.
# Author: Nicolas Delon <nicolas.delon@prelude-ids.com>
#
# This file is part of the PreludeDB library.
#
# 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, 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; see the file COPYING.  If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

import sys
import os, os.path
import time

import cgi
import urllib
import mimetypes
import shutil
import getopt

import SocketServer
import BaseHTTPServer
from prewikka import localization
from prewikka import Core, Request, siteconfig


class PrewikkaServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
    def __init__(self, config, *args, **kwargs):
        self.core = Core.get_core_from_config(config, threaded=True)
        apply(BaseHTTPServer.HTTPServer.__init__, (self,) + args, kwargs)
        


class PrewikkaRequestHandler(Request.Request, BaseHTTPServer.BaseHTTPRequestHandler):
    def getCookieString(self):
        return self.headers.get("Cookie")

    def getQueryString(self):
        return self._query_string

    def getReferer(self):
        try:
            return self.input_headers["referer"]
        except KeyError:
            return ""

    def write(self, data):
        self.wfile.write(data)
    
    def read(self, *args, **kwargs):
        return apply(self.rfile.read, args, kwargs)
    
    def log_request(self, *args, **kwargs):
        pass

    def log_error(self, *args, **kwargs):
        pass

    def _processDynamic(self, arguments):
        self.input_headers.update(self.headers)
        
        for name, value in arguments.items():
            self.arguments[name] = (len(value) == 1) and value[0] or value

        self.server.core.process(self)
        
    def sendResponse(self):
        self.send_response(200)
        Request.Request.sendResponse(self)

    def _processStatic(self):
        filename = os.path.abspath(siteconfig.htdocs_dir + "/" + urllib.unquote(self.path[len("prewikka/"):]))
        if filename.find(os.path.abspath(siteconfig.htdocs_dir)) != 0:
            self.send_error(403, "Request Forbidden")
            return
        
        # the following piece of code is from tracd of the trac project
        # (http://www.edgewall.com/products/trac/)
        try:
            f = open(filename, 'r')
        except IOError:
            self.send_error(404, "File not found")
            return
        
        self.send_response(200)
        mtype, enc = mimetypes.guess_type(filename)
        stat = os.fstat(f.fileno())
        content_length = stat[6]
        last_modified = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(stat[8]))
        self.send_header('Content-Type', mtype)
        self.send_header('Content-Length', str(content_length))
        self.send_header('Last-Modified', last_modified)
        self.end_headers()
        shutil.copyfileobj(f, self.wfile)
        
    def do_GET(self):
        self._query_string = self.path
        self.init()
        if self.path == "/":
            self._processDynamic({ })
        elif self.path.find("?") == 1:
            self._processDynamic(cgi.parse_qs(self.path[2:]))
        else:
            self._processStatic()

    def do_HEAD(self):
        self.do_GET()

    def do_POST(self):
        self._query_string = self.rfile.read(int(self.headers["Content-Length"]))
        self.init()
        self._processDynamic(cgi.parse_qs((self._query_string)))

    def getClientAddr(self):
        return self.client_address[0]

    def getClientPort(self):
        return self.client_address[1]


def usage():
    print "Usage: %s [options]" % sys.argv[0]
    print
    print "Options:"
    print "-c --config [config]\tConfiguration file to use (default: %s/prewikka.conf)" % siteconfig.conf_dir
    print "-p --port [port]\tPort number to use (default: 8000)"
    print "-a --address [address]\tIP to bind to (default: 0.0.0.0)"
    print
    sys.exit(1)


if __name__ == "__main__":
    config = None
    addr, port = "0.0.0.0", 8000
    
    opts, args = getopt.getopt(sys.argv[1:], "hc:a:p:", ["help", "config=", "address=", "port="])
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()

        elif opt in ("-a", "--address"):
            addr = arg
		
        elif opt in ("-p", "--port"):
            port = int(arg)

        elif opt in ("-c", "--config"):
            config = arg

    server = PrewikkaServer(config, (addr, port), PrewikkaRequestHandler)
    server.serve_forever()
