2012-03-12 15:41:55 +01:00
|
|
|
#!/usr/bin/python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2012-03-18 04:16:10 +01:00
|
|
|
# Licensed under GNU General Public License v3 or later
|
|
|
|
# Written by Sebastian Lohff (seba@seba-geek.de)
|
|
|
|
# http://seba-geek.de/stuff/servefile/
|
|
|
|
# v0.3.1
|
2012-03-12 15:41:55 +01:00
|
|
|
|
2012-03-18 02:04:58 +01:00
|
|
|
import argparse
|
2012-03-12 15:41:55 +01:00
|
|
|
import BaseHTTPServer
|
2012-03-18 01:42:03 +01:00
|
|
|
import commands
|
2012-03-12 15:41:55 +01:00
|
|
|
import urllib
|
2012-03-18 01:42:03 +01:00
|
|
|
import os
|
2012-03-12 15:41:55 +01:00
|
|
|
import SocketServer
|
|
|
|
import socket
|
2012-03-18 01:42:03 +01:00
|
|
|
from stat import ST_SIZE
|
2012-03-18 05:08:49 +01:00
|
|
|
from subprocess import Popen, PIPE
|
2012-03-18 01:42:03 +01:00
|
|
|
import sys
|
2012-03-12 15:41:55 +01:00
|
|
|
|
|
|
|
class FileHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
|
|
|
fileName = "Undefined"
|
|
|
|
filePath = "/dev/null"
|
|
|
|
fileLength = 0
|
|
|
|
blockSize = 1024 * 1024
|
|
|
|
|
|
|
|
def do_GET(self):
|
|
|
|
if urllib.unquote(self.path) != "/" + self.fileName:
|
|
|
|
self.send_response(302)
|
|
|
|
self.send_header('Location', '/' + self.fileName)
|
|
|
|
self.end_headers()
|
|
|
|
return
|
|
|
|
|
|
|
|
myfile = open(self.filePath, 'rb')
|
|
|
|
|
|
|
|
# find out if this is a continuing download
|
|
|
|
fromto = None
|
2012-03-18 00:21:55 +01:00
|
|
|
if "Range" in self.headers:
|
|
|
|
cont = self.headers.get("Range").split("=")
|
2012-03-12 15:41:55 +01:00
|
|
|
if len(cont) > 1 and cont[0] == 'bytes':
|
|
|
|
fromto = cont[1].split('-')
|
|
|
|
if len(fromto) > 1:
|
|
|
|
if fromto[1] == '':
|
|
|
|
fromto[1] = self.fileLength-1
|
|
|
|
fromto[0] = int(fromto[0])
|
|
|
|
fromto[1] = int(fromto[1])
|
|
|
|
if fromto[0] >= self.fileLength or fromto[0] < 0 or fromto[1] >= self.fileLength or fromto[1]-fromto[0] < 0:
|
|
|
|
# oops, already done!
|
|
|
|
self.send_response(416)
|
|
|
|
self.send_header('Content-Range', 'bytes */%s' % self.fileLength)
|
|
|
|
self.end_headers()
|
|
|
|
return
|
|
|
|
# now we can wind the file *brrrrrr*
|
|
|
|
myfile.seek(fromto[0])
|
|
|
|
|
|
|
|
if fromto != None:
|
|
|
|
self.send_response(216)
|
|
|
|
self.send_header('Content-Range', 'bytes %s-%s/%s' % (fromto[0], fromto[1], self.fileLength))
|
|
|
|
self.send_header('Content-Length', fromto[1]-fromto[0]+1)
|
|
|
|
else:
|
|
|
|
self.send_response(200)
|
|
|
|
self.send_header('Content-Length', self.fileLength)
|
|
|
|
self.send_header('Content-Disposition', 'attachment; filename="%s"' % self.fileName)
|
|
|
|
self.send_header('Content-type', 'application/octet-stream')
|
|
|
|
self.send_header('Content-Transfer-Encoding', ' binary')
|
|
|
|
self.end_headers()
|
|
|
|
block = self.getChunk(myfile, fromto)
|
|
|
|
while block:
|
|
|
|
try:
|
|
|
|
self.wfile.write(block)
|
|
|
|
except socket.error, e:
|
|
|
|
print "%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1])
|
|
|
|
return
|
|
|
|
block = self.getChunk(myfile, fromto)
|
|
|
|
myfile.close()
|
|
|
|
print "%s finished downloading" % (self.client_address[0])
|
|
|
|
return
|
|
|
|
|
|
|
|
def getChunk(self, myfile, fromto):
|
2012-03-18 00:21:55 +01:00
|
|
|
if fromto and myfile.tell()+self.blockSize >= fromto[1]:
|
2012-03-12 15:41:55 +01:00
|
|
|
readsize = fromto[1]-myfile.tell()+1
|
|
|
|
else:
|
|
|
|
readsize = self.blockSize
|
|
|
|
return myfile.read(readsize)
|
|
|
|
|
|
|
|
class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def main():
|
2012-03-18 02:04:58 +01:00
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('filename', metavar='file/directory', type=str)
|
|
|
|
parser.add_argument('-p', '--port', type=int, default=8080, \
|
|
|
|
help='port to listen on')
|
2012-03-12 15:41:55 +01:00
|
|
|
|
2012-03-18 02:04:58 +01:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
2012-03-12 15:41:55 +01:00
|
|
|
try:
|
2012-03-18 02:04:58 +01:00
|
|
|
testit = open(args.filename, 'r')
|
2012-03-12 15:41:55 +01:00
|
|
|
testit.close()
|
|
|
|
FileHandler.filePath = sys.argv[1]
|
2012-03-18 02:04:58 +01:00
|
|
|
FileHandler.fileName = os.path.basename(args.filename)
|
|
|
|
FileHandler.fileLength = os.stat(args.filename)[ST_SIZE]
|
2012-03-12 15:41:55 +01:00
|
|
|
except IOError:
|
|
|
|
print "Error: Could not open file!"
|
2012-03-18 02:04:58 +01:00
|
|
|
sys.exit(3)
|
|
|
|
|
|
|
|
server = ThreadedHTTPServer(('', args.port), FileHandler)
|
|
|
|
print "Serving \"%s\" under port %d" % (args.filename, args.port)
|
|
|
|
|
2012-03-12 15:41:55 +01:00
|
|
|
# print urls with local network adresses
|
2012-03-18 02:04:58 +01:00
|
|
|
print "\nSome addresses this file will be available under:"
|
|
|
|
|
2012-03-18 05:08:49 +01:00
|
|
|
# ip and ifconfig sometimes are located in /sbin/
|
|
|
|
os.environ['PATH'] += ':/sbin:/usr/sbin'
|
|
|
|
proc = Popen(r"ip addr|" + \
|
|
|
|
"sed -n -e 's/.*inet6\? \([0-9.a-fA-F:]\+\)\/.*/\\1/ p'|" + \
|
|
|
|
"grep -v '^fe80\|^127.0.0.1\|^::1'", shell=True, stdout=PIPE)
|
|
|
|
if proc.wait() != 0:
|
|
|
|
# ip failed somehow, falling back to ifconfig
|
|
|
|
oldLang = os.environ.get("LC_ALL", None)
|
|
|
|
os.environ['LC_ALL'] = "C"
|
|
|
|
proc = Popen(r"ifconfig|" + \
|
|
|
|
"sed -n 's/.*inet6\? addr: \?\([0-9a-fA-F.:]*\).*/" + \
|
|
|
|
"\\1/p'|" + \
|
|
|
|
"grep -v '^fe80\|^127.0.0.1\|^::1'", \
|
|
|
|
shell=True, stdout=PIPE, stderr=PIPE)
|
|
|
|
if oldLang:
|
|
|
|
os.environ['LC_ALL'] = oldLang
|
|
|
|
else:
|
|
|
|
del(os.environ['LC_ALL'])
|
|
|
|
if proc.wait() != 0:
|
|
|
|
print "Error: Could not locate any ips for you."
|
|
|
|
proc = None
|
|
|
|
if proc:
|
|
|
|
ips = proc.stdout.read().strip()
|
|
|
|
for ip in ips.split("\n"):
|
|
|
|
if ip.find(":") >= 0:
|
|
|
|
# ipv6
|
|
|
|
ip = "[%s]" % ip
|
|
|
|
# FIXME: When BaseHTTP supports ipv6 properly, delete this line
|
|
|
|
continue
|
|
|
|
print "http://%s:%d/" % (ip, args.port)
|
2012-03-18 02:04:58 +01:00
|
|
|
|
2012-03-12 15:41:55 +01:00
|
|
|
try:
|
|
|
|
server.serve_forever()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
server.socket.close()
|
|
|
|
print "Good bye.."
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|