onionshare_cli 2.7__tar.gz → 2.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/PKG-INFO +1 -1
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/__init__.py +6 -2
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/censorship.py +4 -2
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/common.py +28 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/meek.py +12 -2
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/onion.py +9 -3
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/settings.py +2 -2
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/share_mode.py +13 -32
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/pyproject.toml +1 -1
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/mode_settings.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/onionshare.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/css/style.css +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/ajax.gif +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/favicon.ico +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/logo.png +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/logo_large.png +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/web_file.png +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/web_folder.png +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/js/chat.js +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/js/jquery-3.7.1.slim.min.js +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/js/receive.js +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/js/send.js +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/js/socket.io.min.js +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/403.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/404.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/405.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/413.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/500.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/chat.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/denied.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/listing.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/receive.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/send.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/thankyou.html +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template-meek +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template-obfs4 +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template-snowflake +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template-webtunnel +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/wordlist.txt +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/__init__.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/chat_mode.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/receive_mode.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/send_base_mode.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/web.py +0 -0
- {onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/web/website_mode.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: onionshare_cli
|
|
3
|
-
Version: 2.7
|
|
3
|
+
Version: 2.7.1
|
|
4
4
|
Summary: Securely and anonymously share files, host websites, and chat with friends using the Tor network
|
|
5
5
|
License: GPL-3.0-or-later
|
|
6
6
|
Keywords: onion,share,onionshare,tor,anonymous,web server
|
|
@@ -470,8 +470,12 @@ def main(cwd=None):
|
|
|
470
470
|
sys.exit(1)
|
|
471
471
|
|
|
472
472
|
if mode == "share":
|
|
473
|
-
# Prepare files to share
|
|
474
|
-
|
|
473
|
+
# Prepare files to share. A single file is served as-is; only multiple
|
|
474
|
+
# files or folders are compressed into a zip file.
|
|
475
|
+
if len(filenames) == 1 and os.path.isfile(filenames[0]):
|
|
476
|
+
print("Preparing file.")
|
|
477
|
+
else:
|
|
478
|
+
print("Compressing files.")
|
|
475
479
|
try:
|
|
476
480
|
web.share_mode.set_file_info(filenames)
|
|
477
481
|
except OSError as e:
|
|
@@ -53,8 +53,10 @@ class CensorshipCircumvention(object):
|
|
|
53
53
|
self.api_proxies = self.meek.meek_proxies
|
|
54
54
|
if onion:
|
|
55
55
|
self.onion = onion
|
|
56
|
-
if not self.onion.is_authenticated:
|
|
57
|
-
|
|
56
|
+
if not self.onion.is_authenticated():
|
|
57
|
+
# Tor isn't connected, so leave api_proxies empty. The request_*
|
|
58
|
+
# methods refuse to run without a proxy, so nothing is sent.
|
|
59
|
+
return
|
|
58
60
|
else:
|
|
59
61
|
self.common.log(
|
|
60
62
|
"CensorshipCircumvention",
|
|
@@ -673,6 +673,34 @@ class Common:
|
|
|
673
673
|
eta = remaining_bytes / download_rate
|
|
674
674
|
return Common.format_seconds(eta)
|
|
675
675
|
|
|
676
|
+
def drain_subprocess_output(self, stream, module):
|
|
677
|
+
"""
|
|
678
|
+
Continuously read a subprocess's output pipe on a daemon thread, logging
|
|
679
|
+
each line, until the subprocess closes it.
|
|
680
|
+
|
|
681
|
+
A subprocess that writes to a pipe nobody reads will block as soon as the
|
|
682
|
+
pipe's buffer fills up. For tor this freezes the whole process, including
|
|
683
|
+
its control port, so every stem call against it hangs. The buffer is only
|
|
684
|
+
about 4 KiB on Windows (64 KiB on Linux), small enough that tor's log
|
|
685
|
+
output while trying several obfs4 bridges is enough to fill it.
|
|
686
|
+
"""
|
|
687
|
+
|
|
688
|
+
def drain():
|
|
689
|
+
try:
|
|
690
|
+
for line in stream:
|
|
691
|
+
if isinstance(line, bytes):
|
|
692
|
+
line = line.decode("utf-8", errors="replace")
|
|
693
|
+
line = line.rstrip()
|
|
694
|
+
if line:
|
|
695
|
+
self.log(module, "output", line)
|
|
696
|
+
except (OSError, ValueError):
|
|
697
|
+
# The pipe was closed underneath us, e.g. during cleanup
|
|
698
|
+
pass
|
|
699
|
+
|
|
700
|
+
t = threading.Thread(target=drain, daemon=True)
|
|
701
|
+
t.start()
|
|
702
|
+
return t
|
|
703
|
+
|
|
676
704
|
@staticmethod
|
|
677
705
|
def get_available_port(min_port, max_port):
|
|
678
706
|
"""
|
|
@@ -120,8 +120,16 @@ class Meek(object):
|
|
|
120
120
|
universal_newlines=True,
|
|
121
121
|
)
|
|
122
122
|
|
|
123
|
-
#
|
|
124
|
-
|
|
123
|
+
# meek-client logs to stderr. Keep reading it so it can never fill the
|
|
124
|
+
# pipe and block meek-client (the buffer is only ~4 KiB on Windows).
|
|
125
|
+
self.common.drain_subprocess_output(self.meek_proc.stderr, "Meek")
|
|
126
|
+
|
|
127
|
+
# Obtain the host and port that meek is running on. Iterating the pipe
|
|
128
|
+
# ends at EOF, so if meek-client exits without reporting a port we fall
|
|
129
|
+
# through to MeekNotRunning below. (The pipe is in text mode, so the
|
|
130
|
+
# previous iter(readline, b"") sentinel never matched "" at EOF, and
|
|
131
|
+
# this loop spun forever.)
|
|
132
|
+
for line in self.meek_proc.stdout:
|
|
125
133
|
if "CMETHOD meek socks5" in line:
|
|
126
134
|
self.meek_host = line.split(" ")[3].split(":")[0]
|
|
127
135
|
self.meek_port = line.split(" ")[3].split(":")[1].strip()
|
|
@@ -138,6 +146,8 @@ class Meek(object):
|
|
|
138
146
|
break
|
|
139
147
|
|
|
140
148
|
if self.meek_port:
|
|
149
|
+
# Keep draining stdout too, now that we've read the port from it
|
|
150
|
+
self.common.drain_subprocess_output(self.meek_proc.stdout, "Meek")
|
|
141
151
|
self.meek_proxies = {
|
|
142
152
|
"http": f"socks5h://{self.meek_host}:{self.meek_port}",
|
|
143
153
|
"https": f"socks5h://{self.meek_host}:{self.meek_port}",
|
|
@@ -428,7 +428,7 @@ class Onion(object):
|
|
|
428
428
|
self.tor_proc = subprocess.Popen(
|
|
429
429
|
[self.tor_path, "-f", self.tor_torrc],
|
|
430
430
|
stdout=subprocess.PIPE,
|
|
431
|
-
stderr=subprocess.
|
|
431
|
+
stderr=subprocess.STDOUT,
|
|
432
432
|
startupinfo=startupinfo,
|
|
433
433
|
)
|
|
434
434
|
else:
|
|
@@ -440,10 +440,16 @@ class Onion(object):
|
|
|
440
440
|
self.tor_proc = subprocess.Popen(
|
|
441
441
|
[self.tor_path, "-f", self.tor_torrc],
|
|
442
442
|
stdout=subprocess.PIPE,
|
|
443
|
-
stderr=subprocess.
|
|
443
|
+
stderr=subprocess.STDOUT,
|
|
444
444
|
env=env,
|
|
445
445
|
)
|
|
446
446
|
|
|
447
|
+
# tor logs to stdout. If nothing reads it, tor blocks once the pipe's
|
|
448
|
+
# buffer is full, and then stops answering on its control port too.
|
|
449
|
+
# On Windows that buffer is only ~4 KiB, which the log output from
|
|
450
|
+
# trying the built-in obfs4 bridges fills within seconds.
|
|
451
|
+
self.common.drain_subprocess_output(self.tor_proc.stdout, "Tor")
|
|
452
|
+
|
|
447
453
|
# Wait for the tor controller to start
|
|
448
454
|
self.common.log("Onion", "connect", f"tor pid: {self.tor_proc.pid}")
|
|
449
455
|
time.sleep(2)
|
|
@@ -992,7 +998,7 @@ class Onion(object):
|
|
|
992
998
|
builtin_bridges = False
|
|
993
999
|
meek = None
|
|
994
1000
|
# Try obtaining bridges over Tor, if we're connected to it.
|
|
995
|
-
if self.is_authenticated:
|
|
1001
|
+
if self.is_authenticated():
|
|
996
1002
|
self.common.log(
|
|
997
1003
|
"Onion",
|
|
998
1004
|
"update_builtin_bridges",
|
|
@@ -57,7 +57,7 @@ class Settings(object):
|
|
|
57
57
|
self.available_locales = {
|
|
58
58
|
#"af": "Afrikaans", # Afrikaans
|
|
59
59
|
#"sq": "Shqip", # Albanian
|
|
60
|
-
|
|
60
|
+
"ar": "العربية", # Arabic
|
|
61
61
|
#"be": "Беларуская", # Belarusian
|
|
62
62
|
#"bn": "বাংলা", # Bengali
|
|
63
63
|
#"bg": "Български", #Bulgarian
|
|
@@ -94,7 +94,7 @@ class Settings(object):
|
|
|
94
94
|
#"sk": "Slovenčina", # Slovak
|
|
95
95
|
#"es": "Español", # Spanish
|
|
96
96
|
#"sw": "Kiswahili", # Swahili
|
|
97
|
-
|
|
97
|
+
"sv": "Svenska", # Swedish
|
|
98
98
|
#"ta": "Tamil", # Tamil
|
|
99
99
|
# "te": "తెలుగు", # Telugu
|
|
100
100
|
"tr": "Türkçe", # Turkish
|
|
@@ -126,13 +126,15 @@ class ShareModeWeb(SendBaseModeWeb):
|
|
|
126
126
|
)
|
|
127
127
|
|
|
128
128
|
self.download_etag = None
|
|
129
|
-
self.gzip_etag = None
|
|
130
129
|
self.last_modified = datetime.now(tz=timezone.utc)
|
|
131
130
|
|
|
132
131
|
def define_routes(self):
|
|
133
132
|
"""
|
|
134
133
|
The web app routes for sharing files
|
|
135
134
|
"""
|
|
135
|
+
# Range offsets must refer to the original file, including when a browser
|
|
136
|
+
# resumes a download. Do not let Flask-Compress transform streamed files.
|
|
137
|
+
self.web.app.config["COMPRESS_STREAMS"] = False
|
|
136
138
|
|
|
137
139
|
@self.web.app.route(
|
|
138
140
|
"/", defaults={"path": ""}, methods=["GET"], provide_automatic_options=False
|
|
@@ -156,10 +158,7 @@ class ShareModeWeb(SendBaseModeWeb):
|
|
|
156
158
|
return render_template("denied.html")
|
|
157
159
|
|
|
158
160
|
# If download is allowed to continue, serve download page
|
|
159
|
-
|
|
160
|
-
self.filesize = self.gzip_filesize
|
|
161
|
-
else:
|
|
162
|
-
self.filesize = self.download_filesize
|
|
161
|
+
self.filesize = self.download_filesize
|
|
163
162
|
|
|
164
163
|
return self.render_logic(path)
|
|
165
164
|
|
|
@@ -183,18 +182,11 @@ class ShareModeWeb(SendBaseModeWeb):
|
|
|
183
182
|
# which is outside of the request context
|
|
184
183
|
request_path = request.path
|
|
185
184
|
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
file_to_download = self.gzip_filename
|
|
192
|
-
self.filesize = self.gzip_filesize
|
|
193
|
-
etag = self.gzip_etag
|
|
194
|
-
else:
|
|
195
|
-
file_to_download = self.download_filename
|
|
196
|
-
self.filesize = self.download_filesize
|
|
197
|
-
etag = self.download_etag
|
|
185
|
+
# Serve the same bytes on initial and resumed downloads. Browsers
|
|
186
|
+
# resume using offsets in the decoded file, not a gzip representation.
|
|
187
|
+
file_to_download = self.download_filename
|
|
188
|
+
self.filesize = self.download_filesize
|
|
189
|
+
etag = self.download_etag
|
|
198
190
|
|
|
199
191
|
# for range requests
|
|
200
192
|
range_, status_code = self.get_range_and_status_code(
|
|
@@ -207,7 +199,7 @@ class ShareModeWeb(SendBaseModeWeb):
|
|
|
207
199
|
self.web.add_request(
|
|
208
200
|
self.web.REQUEST_STARTED,
|
|
209
201
|
request_path,
|
|
210
|
-
{"id": history_id
|
|
202
|
+
{"id": history_id},
|
|
211
203
|
)
|
|
212
204
|
|
|
213
205
|
basename = os.path.basename(self.download_filename)
|
|
@@ -225,9 +217,6 @@ class ShareModeWeb(SendBaseModeWeb):
|
|
|
225
217
|
)
|
|
226
218
|
)
|
|
227
219
|
|
|
228
|
-
if use_gzip:
|
|
229
|
-
r.headers.set("Content-Encoding", "gzip")
|
|
230
|
-
|
|
231
220
|
r.headers.set("Content-Length", range_[1] - range_[0] + 1)
|
|
232
221
|
filename_dict = {
|
|
233
222
|
"filename": unidecode(basename),
|
|
@@ -498,23 +487,15 @@ class ShareModeWeb(SendBaseModeWeb):
|
|
|
498
487
|
with open(self.download_filename, "rb") as f:
|
|
499
488
|
self.download_etag = make_etag(f)
|
|
500
489
|
|
|
501
|
-
#
|
|
490
|
+
# Individual-file views store gzipped copies of shared files here.
|
|
491
|
+
# Delete the directory when the share stops.
|
|
502
492
|
self.gzip_tmp_dir = tempfile.TemporaryDirectory(
|
|
503
493
|
dir=self.common.build_tmp_dir()
|
|
504
494
|
)
|
|
505
|
-
self.
|
|
506
|
-
self._gzip_compress(
|
|
507
|
-
self.download_filename, self.gzip_filename, 6, processed_size_callback
|
|
508
|
-
)
|
|
509
|
-
self.gzip_filesize = os.path.getsize(self.gzip_filename)
|
|
510
|
-
with open(self.gzip_filename, "rb") as f:
|
|
511
|
-
self.gzip_etag = make_etag(f)
|
|
495
|
+
self.web.cleanup_tempdirs.append(self.gzip_tmp_dir)
|
|
512
496
|
|
|
513
497
|
self.is_zipped = False
|
|
514
498
|
|
|
515
|
-
# Cleanup this tempfile
|
|
516
|
-
self.web.cleanup_tempdirs.append(self.gzip_tmp_dir)
|
|
517
|
-
|
|
518
499
|
else:
|
|
519
500
|
# Zip up the files and folders
|
|
520
501
|
self.zip_writer = ZipWriter(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/logo_large.png
RENAMED
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/web_file.png
RENAMED
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/img/web_folder.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/static/js/socket.io.min.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/templates/thankyou.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template-snowflake
RENAMED
|
File without changes
|
{onionshare_cli-2.7 → onionshare_cli-2.7.1}/onionshare_cli/resources/torrc_template-webtunnel
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|