#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright 2008 (C) Pierre Duquesne <stackp@online.fr>
# Licensed under the Python Software Foundation License
# (http://www.python.org/psf/license/)

# 20081219 - Initial release

import BaseHTTPServer
import SocketServer
import mimetypes
import optparse
import socket
socket.setdefaulttimeout(3 * 60)
import urllib
import shutil
import sys
import os

files = {}
password = ""

def make_index():
    keys = files.keys()
    keys.sort()
    if password:
        root = '/' + password + '/'
    else:
        root = '/'
    return ('<html><body><pre>' +
            '\n'.join(['<a href="%s">%s</a>' % (root + f, f) for f in keys])+
            '</pre></body></html>').encode('utf-8')


class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

    protocol_version = "HTTP/1.0"

    def do_GET(self):
        path = urllib.unquote(self.path)
        if password != '':
            if path[:len(password)+1] != '/' + password:
                return
            path = path[len(password)+1:]

        if path.lstrip('/') == '':
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(make_index())
        else:
            filename = path.lstrip('/')
            if filename in files:
                localpath = files[filename]
                f = open(localpath, 'rb')
                self.send_response(200)
                self.send_header('Content-type',
                                 mimetypes.guess_type(localpath)[0])
                self.send_header('Content-length', os.fstat(f.fileno())[6])
                self.end_headers()
                shutil.copyfileobj(f, self.wfile)
            else:
                self.send_response(404)
                self.end_headers()


class ThreadedHTTPServer(SocketServer.ThreadingMixIn,
                         BaseHTTPServer.HTTPServer):
    pass

def parse_args():
    "Parse command-line arguments."
    usage = "weblink [options] FILE1 [FILE2 ...]"
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-p', dest='port', type='int', default=8888,
                      help="set the port")
    parser.add_option('--pass', dest='password', default=None,
                      help="set the url-based password")
    parser.add_option('--randompass', dest='randompass', default=False,
                      action='store_true',
                      help="generate a random url-based password")
    options, remainder = parser.parse_args(sys.argv[1:])
    return options, remainder


if __name__ == '__main__':

    options, args = parse_args()

    if options.password:
        password = options.password

    if options.randompass:
        import random
        import string
        charset = string.ascii_letters + string.digits
        password = ''.join(random.sample(charset, 30))

    port = options.port

    # -- Insert file names in the global dictionary ``files``
    for f in args:

        if not os.path.exists(f):
            print "%s does not exist, skipping." % f
            continue

        if os.path.isdir(f):
            print "%s is a directory, skipping." % f
            continue

        base = os.path.basename(f)

        # Get a unique name for the file
        # (for example, /a/file.txt and /b/file.txt will be called
        # file.txt and file-1.txt)
        i = 1
        root, ext = os.path.splitext(base)
        while (base in files):
            base = "%s-%d%s" % (root, i, ext)
            i = i+1

        files[base] = f

    print ""
    print "HTTP server running at http://localhost:%d/%s" % (port, password)
    try:
        ThreadedHTTPServer(('', port), HTTPRequestHandler).serve_forever()
    except KeyboardInterrupt:
        print '^C received, shutting down server'