mirror of
https://github.com/onionshare/onionshare.git
synced 2025-02-23 07:59:50 -05:00
Adds local-only command line flag.
This commit is contained in:
parent
5b03b41bcd
commit
d0b3145e17
@ -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 random import randint
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
@ -8,14 +8,20 @@ def get_platform():
|
|||||||
else:
|
else:
|
||||||
return platform.system()
|
return platform.system()
|
||||||
|
|
||||||
|
def append_lib_on_tails():
|
||||||
if get_platform() == 'Tails':
|
if get_platform() == 'Tails':
|
||||||
sys.path.append(os.path.dirname(__file__)+'/../tails/lib')
|
sys.path.append(os.path.dirname(__file__)+'/../tails/lib')
|
||||||
|
|
||||||
|
append_lib_on_tails()
|
||||||
|
|
||||||
from stem.control import Controller
|
from stem.control import Controller
|
||||||
from stem import SocketError
|
from stem import SocketError
|
||||||
|
|
||||||
from flask import Flask, Markup, Response, request, make_response, send_from_directory, render_template_string
|
from flask import Flask, Markup, Response, request, make_response, send_from_directory, render_template_string
|
||||||
|
|
||||||
|
class NoTor(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
strings = {}
|
strings = {}
|
||||||
@ -23,61 +29,26 @@ strings = {}
|
|||||||
# generate an unguessable string
|
# generate an unguessable string
|
||||||
slug = os.urandom(16).encode('hex')
|
slug = os.urandom(16).encode('hex')
|
||||||
|
|
||||||
# file information
|
# information about the file
|
||||||
filename = filehash = filesize = ''
|
filename = filesize = filehash = None
|
||||||
|
def set_file_info(new_filename, new_filehash, new_filesize):
|
||||||
@app.after_request
|
global filename, filehash, filesize
|
||||||
def after_request(response):
|
filename = new_filename
|
||||||
response.headers.add('Accept-Ranges', 'bytes')
|
filehash = new_filehash
|
||||||
return response
|
filesize = new_filesize
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/{0}".format(slug))
|
@app.route("/{0}".format(slug))
|
||||||
def index():
|
def index():
|
||||||
global filename, filesize, filehash, slug, strings
|
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(),
|
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)
|
slug=slug, filename=os.path.basename(filename), filehash=filehash, filesize=filesize, strings=strings)
|
||||||
|
|
||||||
@app.route("/{0}/download".format(slug))
|
@app.route("/{0}/download".format(slug))
|
||||||
def download():
|
def download():
|
||||||
global filename
|
global filename
|
||||||
|
|
||||||
range_header = request.headers.get('Range', None)
|
|
||||||
if range_header:
|
|
||||||
return send_file_partial(range_header)
|
|
||||||
|
|
||||||
dirname = os.path.dirname(filename)
|
dirname = os.path.dirname(filename)
|
||||||
basename = os.path.basename(filename)
|
basename = os.path.basename(filename)
|
||||||
return send_from_directory(dirname, basename, as_attachment=True)
|
return send_from_directory(dirname, basename, as_attachment=True)
|
||||||
@ -120,9 +91,55 @@ def load_strings(default="en"):
|
|||||||
lang = lc[:2]
|
lang = lc[:2]
|
||||||
if lang in translated:
|
if lang in translated:
|
||||||
strings = translated[lang]
|
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():
|
def main():
|
||||||
global filename, filehash, filesize
|
|
||||||
load_strings()
|
load_strings()
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
@ -135,56 +152,24 @@ def main():
|
|||||||
|
|
||||||
if not (filename and os.path.isfile(filename)):
|
if not (filename and os.path.isfile(filename)):
|
||||||
sys.exit(strings["not_a_file"].format(filename))
|
sys.exit(strings["not_a_file"].format(filename))
|
||||||
|
filename = os.path.abspath(filename)
|
||||||
|
|
||||||
# calculate filehash, file size
|
port = choose_port()
|
||||||
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()
|
|
||||||
|
|
||||||
local_host = "127.0.0.1:{0}".format(port)
|
local_host = "127.0.0.1:{0}".format(port)
|
||||||
|
|
||||||
if not local_only:
|
if not local_only:
|
||||||
# connect to the tor controlport
|
# try starting hidden service
|
||||||
print strings["connecting_ctrlport"].format(port)
|
print strings["connecting_ctrlport"].format(port)
|
||||||
controlports = [9051, 9151]
|
|
||||||
controller = False
|
|
||||||
|
|
||||||
for controlport in controlports:
|
|
||||||
try:
|
try:
|
||||||
if not controller:
|
onion_host = start_hidden_service(port)
|
||||||
controller = Controller.from_port(port=controlport)
|
except NoTor as e:
|
||||||
except SocketError:
|
sys.exit(e.args[0])
|
||||||
pass
|
|
||||||
|
|
||||||
if not controller:
|
# startup
|
||||||
sys.exit(strings["cant_connect_ctrlport"].format(controlports))
|
print strings["calculating_sha1"]
|
||||||
|
filehash, filesize = file_crunching(filename)
|
||||||
controller.authenticate()
|
set_file_info(filename, filehash, filesize)
|
||||||
|
|
||||||
# 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
|
|
||||||
tails_open_port(port)
|
tails_open_port(port)
|
||||||
|
|
||||||
# instructions
|
|
||||||
print '\n' + strings["give_this_url"]
|
print '\n' + strings["give_this_url"]
|
||||||
if local_only:
|
if local_only:
|
||||||
print 'http://{0}/{1}'.format(local_host, slug)
|
print 'http://{0}/{1}'.format(local_host, slug)
|
||||||
@ -194,7 +179,7 @@ def main():
|
|||||||
print strings["ctrlc_to_stop"]
|
print strings["ctrlc_to_stop"]
|
||||||
|
|
||||||
# start the web server
|
# start the web server
|
||||||
app.run(port=port, debug=True)
|
app.run(port=port)
|
||||||
print '\n'
|
print '\n'
|
||||||
|
|
||||||
# shutdown
|
# shutdown
|
||||||
|
Loading…
x
Reference in New Issue
Block a user