134 lines
3.8 KiB
Python
Executable File
134 lines
3.8 KiB
Python
Executable File
#!/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'
|
|
|
|
|