You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
servefile/servefile

131 lines
3.7 KiB

#!/usr/bin/python
# -*- coding: utf-8 -*-
# written by seba (seba-geek.de) :)
# v0.3
import BaseHTTPServer
import commands
import urllib
import os
import SocketServer
import socket
from stat import ST_SIZE
import sys
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
if "Range" in self.headers:
cont = self.headers.get("Range").split("=")
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):
if fromto and myfile.tell()+self.blockSize >= fromto[1]:
readsize = fromto[1]-myfile.tell()+1
else:
readsize = self.blockSize
return myfile.read(readsize)
class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
pass
def main():
if len(sys.argv) < 2 or len(sys.argv) > 3 or sys.argv[1] in ('-h', '--help'):
print "Usage: [path to file] <port=8080>"
return
port = 8080
if len(sys.argv) == 3:
try:
port = int(sys.argv[2])
except ValueError:
print "Error: Port should be an int!"
return
try:
testit = open(sys.argv[1], 'r')
testit.close()
FileHandler.filePath = sys.argv[1]
FileHandler.fileName = os.path.basename(sys.argv[1])
FileHandler.fileLength = os.stat(sys.argv[1])[ST_SIZE]
except IOError:
print "Error: Could not open file!"
return
server = ThreadedHTTPServer(('', port), FileHandler)
print "Serving:", sys.argv[1]
print "Port: ", port
print "Ready..."
server.address_family = 10
# print urls with local network adresses
print "Some addresses this file will be available under:"
ips = commands.getoutput(r"/bin/ip addr|sed -n -e 's/.*inet6\? \([0-9.a-fA-F:]\+\)\/.*/\1/ p'|grep -v '^fe80\|^127.0.0.1\|^::1'")
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, port)
try:
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()
print "Good bye.."
if __name__ == '__main__':
main()