Browse Source

Initial commit

Sebastian Lohff 8 years ago
commit
8620869e03
4 changed files with 149 additions and 0 deletions
  1. 2
    0
      .gitignore
  2. 1
    0
      README
  3. 129
    0
      servefile
  4. 17
    0
      setup.py

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
1
+MANIFEST
2
+dist/

+ 1
- 0
README View File

@@ -0,0 +1 @@
1
+This is a STUB.

+ 129
- 0
servefile View File

@@ -0,0 +1,129 @@
1
+#!/usr/bin/python
2
+# -*- coding: utf-8 -*-
3
+
4
+# written by seba (seba-geek.de) :)
5
+# v0.3
6
+
7
+import BaseHTTPServer
8
+import sys
9
+import os
10
+import urllib
11
+from stat import ST_SIZE
12
+import SocketServer
13
+import socket
14
+import commands
15
+
16
+class FileHandler(BaseHTTPServer.BaseHTTPRequestHandler):
17
+	fileName = "Undefined"
18
+	filePath = "/dev/null"
19
+	fileLength = 0
20
+	blockSize = 1024 * 1024
21
+	
22
+	def do_GET(self):
23
+		if urllib.unquote(self.path) != "/" + self.fileName:
24
+			self.send_response(302)
25
+			self.send_header('Location', '/' + self.fileName)
26
+			self.end_headers()
27
+			return
28
+
29
+		myfile = open(self.filePath, 'rb')
30
+		
31
+		# find out if this is a continuing download
32
+		fromto = None
33
+		cont =  self.headers.get("Range")
34
+		if cont != None:
35
+			cont = cont.split("=")
36
+			if len(cont) > 1 and cont[0] == 'bytes':
37
+				fromto = cont[1].split('-')
38
+				if len(fromto) > 1:
39
+					if fromto[1] == '':
40
+						fromto[1] = self.fileLength-1
41
+					fromto[0] = int(fromto[0])
42
+					fromto[1] = int(fromto[1])
43
+					if fromto[0] >= self.fileLength or fromto[0] < 0 or fromto[1] >= self.fileLength or fromto[1]-fromto[0] < 0:
44
+						# oops, already done!
45
+						self.send_response(416)
46
+						self.send_header('Content-Range', 'bytes */%s' % self.fileLength)
47
+						self.end_headers()
48
+						return
49
+					# now we can wind the file *brrrrrr*
50
+					myfile.seek(fromto[0])
51
+		
52
+		if fromto != None:
53
+			self.send_response(216)
54
+			self.send_header('Content-Range', 'bytes %s-%s/%s' % (fromto[0], fromto[1], self.fileLength))
55
+			self.send_header('Content-Length', fromto[1]-fromto[0]+1)
56
+		else:
57
+			self.send_response(200)
58
+			self.send_header('Content-Length', self.fileLength)
59
+		self.send_header('Content-Disposition', 'attachment; filename="%s"' % self.fileName)
60
+		self.send_header('Content-type', 'application/octet-stream')
61
+		self.send_header('Content-Transfer-Encoding', ' binary')
62
+		self.end_headers()
63
+		block = self.getChunk(myfile, fromto)
64
+		while block:
65
+			try:
66
+				self.wfile.write(block)
67
+			except socket.error, e:
68
+				print "%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1])
69
+				return
70
+			block = self.getChunk(myfile, fromto)
71
+		myfile.close()
72
+		print "%s finished downloading" % (self.client_address[0])
73
+		return
74
+	
75
+	def getChunk(self, myfile, fromto):
76
+		if fromto != None and myfile.tell()+self.blockSize >= fromto[1]:
77
+			readsize = fromto[1]-myfile.tell()+1
78
+		else:
79
+			readsize = self.blockSize
80
+		return myfile.read(readsize)
81
+
82
+class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
83
+	pass
84
+
85
+def main():
86
+	if len(sys.argv) < 2 or len(sys.argv) > 3 or sys.argv[1] in ('-h', '--help'):
87
+		print "Usage: [path to file] <port=8080>"
88
+		return
89
+	
90
+	port = 8080
91
+	if len(sys.argv) == 3:
92
+		try:
93
+			port = int(sys.argv[2])
94
+		except ValueError:
95
+			print "Error: Port should be an int!"
96
+			return
97
+	
98
+	try:
99
+		testit = open(sys.argv[1], 'r')
100
+		testit.close()
101
+		FileHandler.filePath = sys.argv[1]
102
+		FileHandler.fileName = os.path.basename(sys.argv[1])
103
+		FileHandler.fileLength = os.stat(sys.argv[1])[ST_SIZE]
104
+	except IOError:
105
+		print "Error: Could not open file!"
106
+		return
107
+	
108
+	server = ThreadedHTTPServer(('', port), FileHandler)
109
+	print "Serving:", sys.argv[1]
110
+	print "Port: ", port
111
+	print "Ready..."
112
+	server.address_family = 10
113
+	# print urls with local network adresses
114
+	print "Some addresses this file will be available under:"
115
+	ips = commands.getoutput(r"/sbin/ifconfig |grep 'inet6\?'|grep -v 127.0.0.1|grep -v ' fe80'|grep -v ::1|sed -n 's/.*inet6\?[a-zA-Z: -]\+\([0-9a-fA-F.:]*\).*/\1/p'")
116
+	for ip in ips.split("\n"):
117
+		if ip.find(":") >= 0:
118
+			ip = "[%s]" % ip # must be v6...
119
+			continue	# FIXME: When BaseHTTP supports ipv6 properly, delete this line
120
+		print "http://%s:%d" % (ip, port)
121
+	
122
+	try:
123
+		server.serve_forever()
124
+	except KeyboardInterrupt:
125
+		server.socket.close()
126
+	print "Good bye.."
127
+
128
+if __name__ == '__main__':
129
+	main()

+ 17
- 0
setup.py View File

@@ -0,0 +1,17 @@
1
+#!/usr/bin/python
2
+
3
+from distutils.core import setup
4
+
5
+setup(
6
+	name='servefile',
7
+	description='Script to serve files via a small HTTP server',
8
+	long_description='Script to serve files via a small HTTP server. The server redirects all http requests to the file, so only IP and port must be given to another user to access the file.',
9
+	platforms='posix',
10
+	version='0.3',
11
+	license='GPLv3 or later',
12
+	url='http://seba-geek.de/stuff/servefile/',
13
+	author='Sebastian Lohff',
14
+	author_email='seba@someserver.de',
15
+	scripts=['servefile'],
16
+)
17
+

Loading…
Cancel
Save