Adds local-only command line flag.

This commit is contained in:
Joshua Thayer 2014-06-05 16:11:21 -07:00
parent 5b03b41bcd
commit d0b3145e17

View File

@ -1,4 +1,4 @@
import os, sys, subprocess, time, hashlib, platform, json, locale, socket, re, argparse
import os, sys, subprocess, time, hashlib, platform, json, locale, socket, argparse
from random import randint
from functools import wraps
@ -8,14 +8,20 @@ def get_platform():
else:
return platform.system()
def append_lib_on_tails():
if get_platform() == 'Tails':
sys.path.append(os.path.dirname(__file__)+'/../tails/lib')
append_lib_on_tails()
from stem.control import Controller
from stem import SocketError
from flask import Flask, Markup, Response, request, make_response, send_from_directory, render_template_string
class NoTor(Exception):
pass
app = Flask(__name__)
strings = {}
@ -23,61 +29,26 @@ strings = {}
# generate an unguessable string
slug = os.urandom(16).encode('hex')
# file information
filename = filehash = filesize = ''
@app.after_request
def after_request(response):
response.headers.add('Accept-Ranges', 'bytes')
return response
def send_file_partial(range_header):
global filename
dirname = os.path.dirname(filename)
basename = os.path.basename(filename)
size = os.path.getsize(filename)
byte1, byte2 = 0, None
m = re.search('(\d+)-(\d*)', range_header)
g = m.groups()
if g[0]: byte1 = int(g[0])
if g[1]: byte2 = int(g[1])
length = size - byte1
if byte2 is not None:
length = (byte2 - byte1) + 1
data = None
with open(filename, 'rb') as f:
f.seek(byte1)
data = f.read(length)
rv = Response(data,
206,
# mimetype=mimetypes.guess_type(path)[0],
direct_passthrough=True)
rv.headers.add('Content-Range', 'bytes {0}-{1}/{2}'.format(byte1, byte1 + length - 1, size))
return rv
# information about the file
filename = filesize = filehash = None
def set_file_info(new_filename, new_filehash, new_filesize):
global filename, filehash, filesize
filename = new_filename
filehash = new_filehash
filesize = new_filesize
@app.route("/{0}".format(slug))
def index():
global filename, filesize, filehash, slug, strings
print 'filename: {0}'.format(filename)
print 'filehash: {0}'.format(filehash)
print 'filesize: {0}'.format(filesize)
return render_template_string(open('{0}/index.html'.format(os.path.dirname(__file__))).read(),
slug=slug, filename=os.path.basename(filename), filehash=filehash, filesize=filesize, strings=strings)
@app.route("/{0}/download".format(slug))
def download():
global filename
range_header = request.headers.get('Range', None)
if range_header:
return send_file_partial(range_header)
dirname = os.path.dirname(filename)
basename = os.path.basename(filename)
return send_from_directory(dirname, basename, as_attachment=True)
@ -120,9 +91,55 @@ def load_strings(default="en"):
lang = lc[:2]
if lang in translated:
strings = translated[lang]
return strings
def file_crunching(filename):
# calculate filehash, file size
BLOCKSIZE = 65536
hasher = hashlib.sha1()
with open(filename, 'rb') as f:
buf = f.read(BLOCKSIZE)
while len(buf) > 0:
hasher.update(buf)
buf = f.read(BLOCKSIZE)
filehash = hasher.hexdigest()
filesize = os.path.getsize(filename)
return filehash, filesize
def choose_port():
# let the OS choose a port
tmpsock = socket.socket()
tmpsock.bind(("127.0.0.1", 0))
port = tmpsock.getsockname()[1]
tmpsock.close()
return port
def start_hidden_service(port):
# connect to the tor controlport
controlports = [9051, 9151]
controller = False
for controlport in controlports:
try:
controller = Controller.from_port(port=controlport)
except SocketError:
pass
if not controller:
raise NoTor(strings["cant_connect_ctrlport"].format(controlports))
controller.authenticate()
# set up hidden service
controller.set_options([
('HiddenServiceDir', get_hidden_service_dir(port)),
('HiddenServicePort', '80 127.0.0.1:{0}'.format(port))
])
onion_host = get_hidden_service_hostname(port)
return onion_host
def main():
global filename, filehash, filesize
load_strings()
parser = argparse.ArgumentParser()
@ -135,56 +152,24 @@ def main():
if not (filename and os.path.isfile(filename)):
sys.exit(strings["not_a_file"].format(filename))
filename = os.path.abspath(filename)
# calculate filehash, file size
print strings["calculating_sha1"]
BLOCKSIZE = 65536
hasher = hashlib.sha1()
with open(filename, 'rb') as f:
buf = f.read(BLOCKSIZE)
while len(buf) > 0:
hasher.update(buf)
buf = f.read(BLOCKSIZE)
filehash = hasher.hexdigest()
filesize = os.path.getsize(filename)
# let the OS choose a port
tmpsock = socket.socket()
tmpsock.bind(("127.0.0.1", 0))
port = tmpsock.getsockname()[1]
tmpsock.close()
port = choose_port()
local_host = "127.0.0.1:{0}".format(port)
if not local_only:
# connect to the tor controlport
# try starting hidden service
print strings["connecting_ctrlport"].format(port)
controlports = [9051, 9151]
controller = False
for controlport in controlports:
try:
if not controller:
controller = Controller.from_port(port=controlport)
except SocketError:
pass
onion_host = start_hidden_service(port)
except NoTor as e:
sys.exit(e.args[0])
if not controller:
sys.exit(strings["cant_connect_ctrlport"].format(controlports))
controller.authenticate()
# set up hidden service
controller.set_options([
('HiddenServiceDir', get_hidden_service_dir(port)),
('HiddenServicePort', '80 127.0.0.1:{0}'.format(port))
])
onion_host = get_hidden_service_hostname(port)
# punch a hole in the firewall
# startup
print strings["calculating_sha1"]
filehash, filesize = file_crunching(filename)
set_file_info(filename, filehash, filesize)
tails_open_port(port)
# instructions
print '\n' + strings["give_this_url"]
if local_only:
print 'http://{0}/{1}'.format(local_host, slug)
@ -194,7 +179,7 @@ def main():
print strings["ctrlc_to_stop"]
# start the web server
app.run(port=port, debug=True)
app.run(port=port)
print '\n'
# shutdown