onionshare_cli 2.3.1__tar.gz → 2.3.2__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.
Files changed (48) hide show
  1. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/PKG-INFO +5 -4
  2. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/__init__.py +77 -65
  3. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/common.py +239 -9
  4. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/mode_settings.py +8 -2
  5. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/onion.py +27 -33
  6. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/onionshare.py +2 -22
  7. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/css/style.css +7 -0
  8. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/js/chat.js +10 -1
  9. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/js/receive.js +38 -27
  10. onionshare_cli-2.3.2/onionshare_cli/resources/templates/500.html +21 -0
  11. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/chat.html +4 -3
  12. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/listing.html +24 -23
  13. onionshare_cli-2.3.2/onionshare_cli/resources/templates/receive.html +66 -0
  14. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/send.html +9 -8
  15. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/thankyou.html +3 -3
  16. onionshare_cli-2.3.2/onionshare_cli/resources/torrc_template-obfs4 +16 -0
  17. onionshare_cli-2.3.2/onionshare_cli/resources/version.txt +1 -0
  18. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/settings.py +7 -13
  19. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/chat_mode.py +33 -22
  20. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/receive_mode.py +215 -69
  21. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/send_base_mode.py +33 -16
  22. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/share_mode.py +278 -91
  23. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/web.py +86 -31
  24. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/website_mode.py +4 -6
  25. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/pyproject.toml +5 -4
  26. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/setup.py +5 -4
  27. onionshare_cli-2.3.1/onionshare_cli/resources/templates/receive.html +0 -46
  28. onionshare_cli-2.3.1/onionshare_cli/resources/torrc_template-obfs4 +0 -27
  29. onionshare_cli-2.3.1/onionshare_cli/resources/version.txt +0 -1
  30. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/img/ajax.gif +0 -0
  31. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/img/favicon.ico +0 -0
  32. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/img/logo.png +0 -0
  33. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/img/logo_large.png +0 -0
  34. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/img/web_file.png +0 -0
  35. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/img/web_folder.png +0 -0
  36. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/js/jquery-3.5.1.min.js +0 -0
  37. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/js/send.js +0 -0
  38. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/static/js/socket.io.min.js +0 -0
  39. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/401.html +0 -0
  40. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/403.html +0 -0
  41. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/404.html +0 -0
  42. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/405.html +0 -0
  43. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/templates/denied.html +0 -0
  44. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/torrc_template +0 -0
  45. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/torrc_template-meek_lite_amazon +0 -0
  46. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/torrc_template-meek_lite_azure +0 -0
  47. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/resources/wordlist.txt +0 -0
  48. {onionshare_cli-2.3.1 → onionshare_cli-2.3.2}/onionshare_cli/web/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: onionshare-cli
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does _not_ require setting up a separate server or using a third party file-sharing service.
5
5
  License: GPLv3+
6
6
  Author: Micah Lee
@@ -20,14 +20,15 @@ Classifier: Programming Language :: Python :: 3.9
20
20
  Classifier: Topic :: Communications :: File Sharing
21
21
  Classifier: Topic :: Security :: Cryptography
22
22
  Requires-Dist: click
23
+ Requires-Dist: colorama (>=0.4.4,<0.5.0)
23
24
  Requires-Dist: eventlet
24
- Requires-Dist: flask
25
+ Requires-Dist: flask (>=1.1.4,<2.0.0)
25
26
  Requires-Dist: flask-httpauth
26
- Requires-Dist: flask-socketio
27
+ Requires-Dist: flask-socketio (==5.0.1)
27
28
  Requires-Dist: psutil
28
29
  Requires-Dist: pycryptodome
29
30
  Requires-Dist: pysocks
30
- Requires-Dist: requests
31
+ Requires-Dist: requests[socks] (>=2.25.1,<3.0.0)
31
32
  Requires-Dist: setuptools
32
33
  Requires-Dist: stem
33
34
  Requires-Dist: unidecode
@@ -18,13 +18,22 @@ You should have received a copy of the GNU General Public License
18
18
  along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  """
20
20
 
21
- import os, sys, time, argparse, threading
21
+ import os
22
+ import sys
23
+ import time
24
+ import argparse
25
+ import threading
22
26
  from datetime import datetime
23
27
  from datetime import timedelta
24
28
 
25
29
  from .common import Common, CannotFindTor
26
30
  from .web import Web
27
- from .onion import *
31
+ from .onion import (
32
+ TorErrorProtocolError,
33
+ TorTooOldEphemeral,
34
+ TorTooOldStealth,
35
+ Onion,
36
+ )
28
37
  from .onionshare import OnionShare
29
38
  from .mode_settings import ModeSettings
30
39
 
@@ -43,57 +52,7 @@ def main(cwd=None):
43
52
  onionshare uses.
44
53
  """
45
54
  common = Common()
46
-
47
- # Display OnionShare banner
48
- print(f"OnionShare {common.version} | https://onionshare.org/")
49
- reset = "\033[0m"
50
- purple = "\33[95m"
51
- print(purple)
52
- print(" @@@@@@@@@ ")
53
- print(" @@@@@@@@@@@@@@@@@@@ ")
54
- print(" @@@@@@@@@@@@@@@@@@@@@@@@@ ")
55
- print(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ")
56
- print(
57
- " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ___ _ "
58
- )
59
- print(
60
- " @@@@@@ @@@@@@@@@@@@@ / _ \\ (_) "
61
- )
62
- print(
63
- " @@@@ @ @@@@@@@@@@@ | | | |_ __ _ ___ _ __ "
64
- )
65
- print(
66
- " @@@@@@@@ @@@@@@@@@@ | | | | '_ \\| |/ _ \\| '_ \\ "
67
- )
68
- print(
69
- " @@@@@@@@@@@@ @@@@@@@@@@ \\ \\_/ / | | | | (_) | | | | "
70
- )
71
- print(
72
- " @@@@@@@@@@@@@@@@ @@@@@@@@@ \\___/|_| |_|_|\\___/|_| |_| "
73
- )
74
- print(
75
- " @@@@@@@@@ @@@@@@@@@@@@@@@@ _____ _ "
76
- )
77
- print(
78
- " @@@@@@@@@@ @@@@@@@@@@@@ / ___| | "
79
- )
80
- print(
81
- " @@@@@@@@@@ @@@@@@@@ \\ `--.| |__ __ _ _ __ ___ "
82
- )
83
- print(
84
- " @@@@@@@@@@@ @ @@@@ `--. \\ '_ \\ / _` | '__/ _ \\"
85
- )
86
- print(
87
- " @@@@@@@@@@@@@ @@@@@@ /\\__/ / | | | (_| | | | __/"
88
- )
89
- print(
90
- " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \\____/|_| |_|\\__,_|_| \\___|"
91
- )
92
- print(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ")
93
- print(" @@@@@@@@@@@@@@@@@@@@@@@@@ ")
94
- print(" @@@@@@@@@@@@@@@@@@@ ")
95
- print(" @@@@@@@@@ ")
96
- print(reset)
55
+ common.display_banner()
97
56
 
98
57
  # OnionShare CLI in OSX needs to change current working directory (#132)
99
58
  if common.platform == "Darwin":
@@ -143,6 +102,12 @@ def main(cwd=None):
143
102
  help="Filename of persistent session",
144
103
  )
145
104
  # General args
105
+ parser.add_argument(
106
+ "--title",
107
+ metavar="TITLE",
108
+ default=None,
109
+ help="Set a title",
110
+ )
146
111
  parser.add_argument(
147
112
  "--public",
148
113
  action="store_true",
@@ -193,6 +158,24 @@ def main(cwd=None):
193
158
  default=None,
194
159
  help="Receive files: Save files received to this directory",
195
160
  )
161
+ parser.add_argument(
162
+ "--webhook-url",
163
+ metavar="webhook_url",
164
+ default=None,
165
+ help="Receive files: URL to receive webhook notifications",
166
+ )
167
+ parser.add_argument(
168
+ "--disable-text",
169
+ action="store_true",
170
+ dest="disable_text",
171
+ help="Receive files: Disable receiving text messages",
172
+ )
173
+ parser.add_argument(
174
+ "--disable-files",
175
+ action="store_true",
176
+ dest="disable_files",
177
+ help="Receive files: Disable receiving files",
178
+ )
196
179
  # Website args
197
180
  parser.add_argument(
198
181
  "--disable_csp",
@@ -228,6 +211,7 @@ def main(cwd=None):
228
211
  connect_timeout = int(args.connect_timeout)
229
212
  config_filename = args.config
230
213
  persistent_filename = args.persistent
214
+ title = args.title
231
215
  public = bool(args.public)
232
216
  autostart_timer = int(args.autostart_timer)
233
217
  autostop_timer = int(args.autostop_timer)
@@ -235,6 +219,9 @@ def main(cwd=None):
235
219
  client_auth = bool(args.client_auth)
236
220
  autostop_sharing = not bool(args.no_autostop_sharing)
237
221
  data_dir = args.data_dir
222
+ webhook_url = args.webhook_url
223
+ disable_text = args.disable_text
224
+ disable_files = args.disable_files
238
225
  disable_csp = bool(args.disable_csp)
239
226
  verbose = bool(args.verbose)
240
227
 
@@ -273,6 +260,7 @@ def main(cwd=None):
273
260
 
274
261
  if mode_settings.just_created:
275
262
  # This means the mode settings were just created, not loaded from disk
263
+ mode_settings.set("general", "title", title)
276
264
  mode_settings.set("general", "public", public)
277
265
  mode_settings.set("general", "autostart_timer", autostart_timer)
278
266
  mode_settings.set("general", "autostop_timer", autostop_timer)
@@ -283,6 +271,10 @@ def main(cwd=None):
283
271
  if mode == "receive":
284
272
  if data_dir:
285
273
  mode_settings.set("receive", "data_dir", data_dir)
274
+ if webhook_url:
275
+ mode_settings.set("receive", "webhook_url", webhook_url)
276
+ mode_settings.set("receive", "disable_text", disable_text)
277
+ mode_settings.set("receive", "disable_files", disable_files)
286
278
  if mode == "website":
287
279
  mode_settings.set("website", "disable_csp", disable_csp)
288
280
  else:
@@ -325,6 +317,11 @@ def main(cwd=None):
325
317
  if persistent_filename:
326
318
  mode_settings.set(mode, "filenames", filenames)
327
319
 
320
+ # In receive mode, you must allows either text, files, or both
321
+ if mode == "receive" and disable_text and disable_files:
322
+ print("You cannot disable both text and files")
323
+ sys.exit()
324
+
328
325
  # Create the Web object
329
326
  web = Web(common, False, mode_settings, mode)
330
327
 
@@ -348,16 +345,29 @@ def main(cwd=None):
348
345
  except KeyboardInterrupt:
349
346
  print("")
350
347
  sys.exit()
351
- except Exception as e:
348
+ except Exception:
352
349
  sys.exit()
353
350
 
354
351
  # Start the onionshare app
355
352
  try:
356
353
  common.settings.load()
357
- if not mode_settings.get("general", "public"):
358
- web.generate_password(mode_settings.get("onion", "password"))
359
- else:
354
+
355
+ if mode_settings.get("general", "public"):
360
356
  web.password = None
357
+ else:
358
+ web.generate_password(mode_settings.get("onion", "password"))
359
+
360
+ # Receive mode needs to know the tor proxy details for webhooks
361
+ if mode == "receive":
362
+ if local_only:
363
+ web.proxies = None
364
+ else:
365
+ (socks_address, socks_port) = onion.get_tor_socks_port()
366
+ web.proxies = {
367
+ "http": f"socks5h://{socks_address}:{socks_port}",
368
+ "https": f"socks5h://{socks_address}:{socks_port}",
369
+ }
370
+
361
371
  app = OnionShare(common, onion, local_only, autostop_timer)
362
372
  app.choose_port()
363
373
 
@@ -370,7 +380,7 @@ def main(cwd=None):
370
380
  )
371
381
  sys.exit()
372
382
 
373
- app.start_onion_service(mode, mode_settings, False, True)
383
+ app.start_onion_service(mode, mode_settings, False)
374
384
  url = build_url(mode_settings, app, web)
375
385
  schedule = datetime.now() + timedelta(seconds=autostart_timer)
376
386
  if mode == "receive":
@@ -379,7 +389,9 @@ def main(cwd=None):
379
389
  )
380
390
  print("")
381
391
  print(
382
- "Warning: Receive mode lets people upload files to your computer. Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing."
392
+ "Warning: Receive mode lets people upload files to your computer. Some files can potentially take "
393
+ "control of your computer if you open them. Only open things from people you trust, or if you know "
394
+ "what you are doing."
383
395
  )
384
396
  print("")
385
397
  if mode_settings.get("general", "client_auth"):
@@ -412,7 +424,7 @@ def main(cwd=None):
412
424
  except KeyboardInterrupt:
413
425
  print("")
414
426
  sys.exit()
415
- except (TorTooOld, TorErrorProtocolError) as e:
427
+ except (TorTooOldEphemeral, TorTooOldStealth, TorErrorProtocolError) as e:
416
428
  print("")
417
429
  print(e.args[0])
418
430
  sys.exit()
@@ -430,7 +442,6 @@ def main(cwd=None):
430
442
  print("Compressing files.")
431
443
  try:
432
444
  web.share_mode.set_file_info(filenames)
433
- app.cleanup_filenames += web.share_mode.cleanup_filenames
434
445
  except OSError as e:
435
446
  print(e.strerror)
436
447
  sys.exit(1)
@@ -473,7 +484,9 @@ def main(cwd=None):
473
484
  )
474
485
  print("")
475
486
  print(
476
- "Warning: Receive mode lets people upload files to your computer. Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing."
487
+ "Warning: Receive mode lets people upload files to your computer. Some files can potentially take "
488
+ "control of your computer if you open them. Only open things from people you trust, or if you know "
489
+ "what you are doing."
477
490
  )
478
491
  print("")
479
492
 
@@ -514,8 +527,7 @@ def main(cwd=None):
514
527
  print("Stopped because auto-stop timer ran out")
515
528
  web.stop(app.port)
516
529
  break
517
- else:
518
- web.receive_mode.can_upload = False
530
+ web.receive_mode.can_upload = False
519
531
  # Allow KeyboardInterrupt exception to be handled with threads
520
532
  # https://stackoverflow.com/questions/3788208/python-threading-ignores-keyboardinterrupt-exception
521
533
  time.sleep(0.2)
@@ -523,7 +535,7 @@ def main(cwd=None):
523
535
  web.stop(app.port)
524
536
  finally:
525
537
  # Shutdown
526
- app.cleanup()
538
+ web.cleanup()
527
539
  onion.cleanup()
528
540
 
529
541
 
@@ -19,18 +19,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  """
20
20
  import base64
21
21
  import hashlib
22
- import inspect
23
22
  import os
24
23
  import platform
25
24
  import random
26
25
  import socket
27
26
  import sys
28
- import tempfile
29
27
  import threading
30
28
  import time
31
29
  import shutil
32
30
  from pkg_resources import resource_filename
33
31
 
32
+ import colorama
33
+ from colorama import Fore, Back, Style
34
+
34
35
  from .settings import Settings
35
36
 
36
37
 
@@ -48,6 +49,8 @@ class Common:
48
49
  def __init__(self, verbose=False):
49
50
  self.verbose = verbose
50
51
 
52
+ colorama.init(autoreset=True)
53
+
51
54
  # The platform OnionShare is running on
52
55
  self.platform = platform.system()
53
56
  if self.platform.endswith("BSD") or self.platform == "DragonFly":
@@ -57,6 +60,224 @@ class Common:
57
60
  with open(self.get_resource_path("version.txt")) as f:
58
61
  self.version = f.read().strip()
59
62
 
63
+ def display_banner(self):
64
+ """
65
+ Raw ASCII art example:
66
+ ╭───────────────────────────────────────────╮
67
+ │ * ▄▄█████▄▄ * │
68
+ │ ▄████▀▀▀████▄ * │
69
+ │ ▀▀█▀ ▀██▄ │
70
+ │ * ▄█▄ ▀██▄ │
71
+ │ ▄█████▄ ███ -+- │
72
+ │ ███ ▀█████▀ │
73
+ │ ▀██▄ ▀█▀ │
74
+ │ * ▀██▄ ▄█▄▄ * │
75
+ │ * ▀████▄▄▄████▀ │
76
+ │ ▀▀█████▀▀ │
77
+ │ -+- * │
78
+ │ ▄▀▄ ▄▀▀ █ │
79
+ │ █ █ ▀ ▀▄ █ │
80
+ │ █ █ █▀▄ █ ▄▀▄ █▀▄ ▀▄ █▀▄ ▄▀▄ █▄▀ ▄█▄ │
81
+ │ ▀▄▀ █ █ █ ▀▄▀ █ █ ▄▄▀ █ █ ▀▄█ █ ▀▄▄ │
82
+ │ │
83
+ │ v2.3.1 │
84
+ │ │
85
+ │ https://onionshare.org/ │
86
+ ╰───────────────────────────────────────────╯
87
+ """
88
+
89
+ if self.platform == "Windows":
90
+ pass
91
+ else:
92
+ pass
93
+
94
+ print(
95
+ Back.MAGENTA + Fore.WHITE + "╭───────────────────────────────────────────╮"
96
+ )
97
+ print(
98
+ Back.MAGENTA
99
+ + Fore.WHITE
100
+ + "│"
101
+ + Fore.LIGHTMAGENTA_EX
102
+ + " * "
103
+ + Fore.WHITE
104
+ + "▄▄█████▄▄"
105
+ + Fore.LIGHTMAGENTA_EX
106
+ + " * "
107
+ + Fore.WHITE
108
+ + "│"
109
+ )
110
+ print(
111
+ Back.MAGENTA
112
+ + Fore.WHITE
113
+ + "│"
114
+ + Fore.WHITE
115
+ + " ▄████▀▀▀████▄"
116
+ + Fore.LIGHTMAGENTA_EX
117
+ + " * "
118
+ + Fore.WHITE
119
+ + "│"
120
+ )
121
+ print(
122
+ Back.MAGENTA
123
+ + Fore.WHITE
124
+ + "│"
125
+ + Fore.WHITE
126
+ + " ▀▀█▀ ▀██▄ "
127
+ + Fore.WHITE
128
+ + "│"
129
+ )
130
+ print(
131
+ Back.MAGENTA
132
+ + Fore.WHITE
133
+ + "│"
134
+ + Fore.LIGHTMAGENTA_EX
135
+ + " * "
136
+ + Fore.WHITE
137
+ + "▄█▄ ▀██▄ "
138
+ + Fore.WHITE
139
+ + "│"
140
+ )
141
+ print(
142
+ Back.MAGENTA
143
+ + Fore.WHITE
144
+ + "│"
145
+ + Fore.WHITE
146
+ + " ▄█████▄ ███"
147
+ + Fore.LIGHTMAGENTA_EX
148
+ + " -+- "
149
+ + Fore.WHITE
150
+ + "│"
151
+ )
152
+ print(
153
+ Back.MAGENTA
154
+ + Fore.WHITE
155
+ + "│"
156
+ + Fore.WHITE
157
+ + " ███ ▀█████▀ "
158
+ + Fore.WHITE
159
+ + "│"
160
+ )
161
+ print(
162
+ Back.MAGENTA
163
+ + Fore.WHITE
164
+ + "│"
165
+ + Fore.WHITE
166
+ + " ▀██▄ ▀█▀ "
167
+ + Fore.WHITE
168
+ + "│"
169
+ )
170
+ print(
171
+ Back.MAGENTA
172
+ + Fore.WHITE
173
+ + "│"
174
+ + Fore.LIGHTMAGENTA_EX
175
+ + " * "
176
+ + Fore.WHITE
177
+ + "▀██▄ ▄█▄▄"
178
+ + Fore.LIGHTMAGENTA_EX
179
+ + " * "
180
+ + Fore.WHITE
181
+ + "│"
182
+ )
183
+ print(
184
+ Back.MAGENTA
185
+ + Fore.WHITE
186
+ + "│"
187
+ + Fore.LIGHTMAGENTA_EX
188
+ + " * "
189
+ + Fore.WHITE
190
+ + "▀████▄▄▄████▀ "
191
+ + Fore.WHITE
192
+ + "│"
193
+ )
194
+ print(
195
+ Back.MAGENTA
196
+ + Fore.WHITE
197
+ + "│"
198
+ + Fore.WHITE
199
+ + " ▀▀█████▀▀ "
200
+ + Fore.WHITE
201
+ + "│"
202
+ )
203
+ print(
204
+ Back.MAGENTA
205
+ + Fore.WHITE
206
+ + "│"
207
+ + Fore.LIGHTMAGENTA_EX
208
+ + " -+- * "
209
+ + Fore.WHITE
210
+ + "│"
211
+ )
212
+ print(
213
+ Back.MAGENTA
214
+ + Fore.WHITE
215
+ + "│"
216
+ + Fore.WHITE
217
+ + " ▄▀▄ ▄▀▀ █ "
218
+ + Fore.WHITE
219
+ + "│"
220
+ )
221
+ print(
222
+ Back.MAGENTA
223
+ + Fore.WHITE
224
+ + "│"
225
+ + Fore.WHITE
226
+ + " █ █ ▀ ▀▄ █ "
227
+ + Fore.WHITE
228
+ + "│"
229
+ )
230
+ print(
231
+ Back.MAGENTA
232
+ + Fore.WHITE
233
+ + "│"
234
+ + Fore.WHITE
235
+ + " █ █ █▀▄ █ ▄▀▄ █▀▄ ▀▄ █▀▄ ▄▀▄ █▄▀ ▄█▄ "
236
+ + Fore.WHITE
237
+ + "│"
238
+ )
239
+ print(
240
+ Back.MAGENTA
241
+ + Fore.WHITE
242
+ + "│"
243
+ + Fore.WHITE
244
+ + " ▀▄▀ █ █ █ ▀▄▀ █ █ ▄▄▀ █ █ ▀▄█ █ ▀▄▄ "
245
+ + Fore.WHITE
246
+ + "│"
247
+ )
248
+ print(
249
+ Back.MAGENTA + Fore.WHITE + "│ │"
250
+ )
251
+ left_spaces = (43 - len(self.version) - 1) // 2
252
+ right_spaces = left_spaces
253
+ if left_spaces + len(self.version) + 1 + right_spaces < 43:
254
+ right_spaces += 1
255
+ print(
256
+ Back.MAGENTA
257
+ + Fore.WHITE
258
+ + "│"
259
+ + Fore.WHITE
260
+ + f"{' '*left_spaces}v{self.version}{' '*right_spaces}"
261
+ + Fore.WHITE
262
+ + "│"
263
+ )
264
+ print(
265
+ Back.MAGENTA + Fore.WHITE + "│ │"
266
+ )
267
+ print(
268
+ Back.MAGENTA
269
+ + Fore.WHITE
270
+ + "│"
271
+ + Fore.WHITE
272
+ + " https://onionshare.org/ "
273
+ + Fore.WHITE
274
+ + "│"
275
+ )
276
+ print(
277
+ Back.MAGENTA + Fore.WHITE + "╰───────────────────────────────────────────╯"
278
+ )
279
+ print()
280
+
60
281
  def load_settings(self, config=None):
61
282
  """
62
283
  Loading settings, optionally from a custom config json file.
@@ -70,10 +291,11 @@ class Common:
70
291
  """
71
292
  if self.verbose:
72
293
  timestamp = time.strftime("%b %d %Y %X")
73
-
74
- final_msg = f"[{timestamp}] {module}.{func}"
294
+ final_msg = f"{Fore.LIGHTBLACK_EX + Style.DIM}[{timestamp}]{Style.RESET_ALL} {Fore.WHITE + Style.DIM}{module}.{func}{Style.RESET_ALL}"
75
295
  if msg:
76
- final_msg = f"{final_msg}: {msg}"
296
+ final_msg = (
297
+ f"{final_msg}{Fore.WHITE + Style.DIM}: {msg}{Style.RESET_ALL}"
298
+ )
77
299
  print(final_msg)
78
300
 
79
301
  def get_resource_path(self, filename):
@@ -129,16 +351,24 @@ class Common:
129
351
  try:
130
352
  appdata = os.environ["APPDATA"]
131
353
  onionshare_data_dir = f"{appdata}\\OnionShare"
132
- except:
354
+ except Exception:
133
355
  # If for some reason we don't have the 'APPDATA' environment variable
134
356
  # (like running tests in Linux while pretending to be in Windows)
135
- onionshare_data_dir = os.path.expanduser("~/.config/onionshare")
357
+ try:
358
+ xdg_config_home = os.environ["XDG_CONFIG_HOME"]
359
+ onionshare_data_dir = f"{xdg_config_home}/onionshare"
360
+ except Exception:
361
+ onionshare_data_dir = os.path.expanduser("~/.config/onionshare")
136
362
  elif self.platform == "Darwin":
137
363
  onionshare_data_dir = os.path.expanduser(
138
364
  "~/Library/Application Support/OnionShare"
139
365
  )
140
366
  else:
141
- onionshare_data_dir = os.path.expanduser("~/.config/onionshare")
367
+ try:
368
+ xdg_config_home = os.environ["XDG_CONFIG_HOME"]
369
+ onionshare_data_dir = f"{xdg_config_home}/onionshare"
370
+ except Exception:
371
+ onionshare_data_dir = os.path.expanduser("~/.config/onionshare")
142
372
 
143
373
  # Modify the data dir if running tests
144
374
  if getattr(sys, "onionshare_test_mode", False):
@@ -256,7 +486,7 @@ class Common:
256
486
  try:
257
487
  tmpsock.bind(("127.0.0.1", random.randint(min_port, max_port)))
258
488
  break
259
- except OSError as e:
489
+ except OSError:
260
490
  pass
261
491
  _, port = tmpsock.getsockname()
262
492
  return port
@@ -42,6 +42,7 @@ class ModeSettings:
42
42
  },
43
43
  "persistent": {"mode": None, "enabled": False},
44
44
  "general": {
45
+ "title": None,
45
46
  "public": False,
46
47
  "autostart_timer": False,
47
48
  "autostop_timer": False,
@@ -50,7 +51,12 @@ class ModeSettings:
50
51
  "service_id": None,
51
52
  },
52
53
  "share": {"autostop_sharing": True, "filenames": []},
53
- "receive": {"data_dir": self.build_default_receive_data_dir()},
54
+ "receive": {
55
+ "data_dir": self.build_default_receive_data_dir(),
56
+ "webhook_url": None,
57
+ "disable_text": False,
58
+ "disable_files": False,
59
+ },
54
60
  "website": {"disable_csp": False, "filenames": []},
55
61
  "chat": {"room": "default"},
56
62
  }
@@ -123,7 +129,7 @@ class ModeSettings:
123
129
  self.fill_in_defaults()
124
130
  self.common.log("ModeSettings", "load", f"loaded {self.filename}")
125
131
  return
126
- except:
132
+ except Exception:
127
133
  pass
128
134
 
129
135
  # If loading settings didn't work, create the settings file