summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml5
-rw-r--r--cli/onionshare_cli/__init__.py21
-rw-r--r--cli/onionshare_cli/web/chat_mode.py7
-rw-r--r--cli/onionshare_cli/web/receive_mode.py18
-rw-r--r--cli/onionshare_cli/web/send_base_mode.py4
-rw-r--r--cli/onionshare_cli/web/share_mode.py13
-rw-r--r--cli/onionshare_cli/web/web.py64
-rw-r--r--cli/tests/test_cli_common.py2
-rw-r--r--cli/tests/test_cli_settings.py2
-rw-r--r--cli/tests/test_cli_web.py4
-rw-r--r--desktop/src/onionshare/resources/locale/ar.json2
-rw-r--r--desktop/src/onionshare/resources/locale/bn.json2
-rw-r--r--desktop/src/onionshare/resources/locale/ca.json2
-rw-r--r--desktop/src/onionshare/resources/locale/ckb.json2
-rw-r--r--desktop/src/onionshare/resources/locale/da.json2
-rw-r--r--desktop/src/onionshare/resources/locale/de.json2
-rw-r--r--desktop/src/onionshare/resources/locale/el.json2
-rw-r--r--desktop/src/onionshare/resources/locale/en.json9
-rw-r--r--desktop/src/onionshare/resources/locale/es.json2
-rw-r--r--desktop/src/onionshare/resources/locale/fi.json2
-rw-r--r--desktop/src/onionshare/resources/locale/fr.json2
-rw-r--r--desktop/src/onionshare/resources/locale/gl.json2
-rw-r--r--desktop/src/onionshare/resources/locale/hi.json2
-rw-r--r--desktop/src/onionshare/resources/locale/hr.json2
-rw-r--r--desktop/src/onionshare/resources/locale/id.json2
-rw-r--r--desktop/src/onionshare/resources/locale/is.json2
-rw-r--r--desktop/src/onionshare/resources/locale/it.json2
-rw-r--r--desktop/src/onionshare/resources/locale/ja.json2
-rw-r--r--desktop/src/onionshare/resources/locale/lt.json2
-rw-r--r--desktop/src/onionshare/resources/locale/nb_NO.json2
-rw-r--r--desktop/src/onionshare/resources/locale/nl.json2
-rw-r--r--desktop/src/onionshare/resources/locale/pl.json2
-rw-r--r--desktop/src/onionshare/resources/locale/pt_BR.json2
-rw-r--r--desktop/src/onionshare/resources/locale/pt_PT.json2
-rw-r--r--desktop/src/onionshare/resources/locale/ru.json2
-rw-r--r--desktop/src/onionshare/resources/locale/si.json2
-rw-r--r--desktop/src/onionshare/resources/locale/sk.json2
-rw-r--r--desktop/src/onionshare/resources/locale/sr_Latn.json2
-rw-r--r--desktop/src/onionshare/resources/locale/sv.json2
-rw-r--r--desktop/src/onionshare/resources/locale/tr.json2
-rw-r--r--desktop/src/onionshare/resources/locale/uk.json2
-rw-r--r--desktop/src/onionshare/resources/locale/zh_Hans.json2
-rw-r--r--desktop/src/onionshare/resources/locale/zh_Hant.json2
-rw-r--r--desktop/src/onionshare/tab/mode/__init__.py8
-rw-r--r--desktop/src/onionshare/tab/mode/receive_mode/__init__.py5
-rw-r--r--desktop/src/onionshare/tab/server_status.py132
-rw-r--r--desktop/src/onionshare/widgets.py45
-rw-r--r--desktop/tests/gui_base_test.py59
-rw-r--r--desktop/tests/test_gui_chat.py7
-rw-r--r--desktop/tests/test_gui_receive.py7
-rw-r--r--desktop/tests/test_gui_share.py7
-rw-r--r--desktop/tests/test_gui_website.py7
52 files changed, 320 insertions, 170 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3be131b3..175595f3 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,8 +1,3 @@
-# To run the tests, CircleCI needs these environment variables:
-# QT_EMAIL - email address for a Qt account
-# QT_PASSWORD - password for a Qt account
-# (Unfortunately you can't install Qt without logging in.)
-
version: 2
workflows:
version: 2
diff --git a/cli/onionshare_cli/__init__.py b/cli/onionshare_cli/__init__.py
index a359f770..4bc00929 100644
--- a/cli/onionshare_cli/__init__.py
+++ b/cli/onionshare_cli/__init__.py
@@ -201,15 +201,6 @@ def main(cwd=None):
disable_csp = bool(args.disable_csp)
verbose = bool(args.verbose)
- if receive:
- mode = "receive"
- elif website:
- mode = "website"
- elif chat:
- mode = "chat"
- else:
- mode = "share"
-
# Verbose mode?
common.verbose = verbose
@@ -223,16 +214,26 @@ def main(cwd=None):
if persistent_filename:
mode_settings = ModeSettings(common, persistent_filename)
mode_settings.set("persistent", "enabled", True)
- mode_settings.set("persistent", "mode", mode)
else:
mode_settings = ModeSettings(common)
+ if receive:
+ mode = "receive"
+ elif website:
+ mode = "website"
+ elif chat:
+ mode = "chat"
+ else:
+ mode = "share"
+
if mode_settings.just_created:
# This means the mode settings were just created, not loaded from disk
mode_settings.set("general", "title", title)
mode_settings.set("general", "public", public)
mode_settings.set("general", "autostart_timer", autostart_timer)
mode_settings.set("general", "autostop_timer", autostop_timer)
+ if persistent_filename:
+ mode_settings.set("persistent", "mode", mode)
if mode == "share":
mode_settings.set("share", "autostop_sharing", autostop_sharing)
if mode == "receive":
diff --git a/cli/onionshare_cli/web/chat_mode.py b/cli/onionshare_cli/web/chat_mode.py
index f6dc2d1a..e92ce385 100644
--- a/cli/onionshare_cli/web/chat_mode.py
+++ b/cli/onionshare_cli/web/chat_mode.py
@@ -68,15 +68,12 @@ class ChatModeWeb:
)
self.web.add_request(self.web.REQUEST_LOAD, request.path)
- r = make_response(
- render_template(
+ return render_template(
"chat.html",
static_url_path=self.web.static_url_path,
username=session.get("name"),
title=self.web.settings.get("general", "title"),
- )
)
- return self.web.add_security_headers(r)
@self.web.app.route("/update-session-username", methods=["POST"], provide_automatic_options=False)
def update_session_username():
@@ -112,7 +109,7 @@ class ChatModeWeb:
success=False,
)
)
- return self.web.add_security_headers(r)
+ return r
@self.web.socketio.on("joined", namespace="/chat")
def joined(message):
diff --git a/cli/onionshare_cli/web/receive_mode.py b/cli/onionshare_cli/web/receive_mode.py
index 76abb0a8..6b106d37 100644
--- a/cli/onionshare_cli/web/receive_mode.py
+++ b/cli/onionshare_cli/web/receive_mode.py
@@ -86,16 +86,13 @@ class ReceiveModeWeb:
)
self.web.add_request(self.web.REQUEST_LOAD, request.path)
- r = make_response(
- render_template(
- "receive.html",
- static_url_path=self.web.static_url_path,
- disable_text=self.web.settings.get("receive", "disable_text"),
- disable_files=self.web.settings.get("receive", "disable_files"),
- title=self.web.settings.get("general", "title"),
- )
+ return render_template(
+ "receive.html",
+ static_url_path=self.web.static_url_path,
+ disable_text=self.web.settings.get("receive", "disable_text"),
+ disable_files=self.web.settings.get("receive", "disable_files"),
+ title=self.web.settings.get("general", "title")
)
- return self.web.add_security_headers(r)
@self.web.app.route("/upload", methods=["POST"], provide_automatic_options=False)
def upload(ajax=False):
@@ -222,12 +219,11 @@ class ReceiveModeWeb:
)
else:
# It was the last upload and the timer ran out
- r = make_response(
+ return make_response(
render_template("thankyou.html"),
static_url_path=self.web.static_url_path,
title=self.web.settings.get("general", "title"),
)
- return self.web.add_security_headers(r)
@self.web.app.route("/upload-ajax", methods=["POST"], provide_automatic_options=False)
def upload_ajax_public():
diff --git a/cli/onionshare_cli/web/send_base_mode.py b/cli/onionshare_cli/web/send_base_mode.py
index e448d2dd..27de598a 100644
--- a/cli/onionshare_cli/web/send_base_mode.py
+++ b/cli/onionshare_cli/web/send_base_mode.py
@@ -149,10 +149,9 @@ class SendBaseModeWeb:
# If filesystem_path is None, this is the root directory listing
files, dirs = self.build_directory_listing(path, filenames, filesystem_path)
- r = self.directory_listing_template(
+ return self.directory_listing_template(
path, files, dirs, breadcrumbs, breadcrumbs_leaf
)
- return self.web.add_security_headers(r)
def build_directory_listing(self, path, filenames, filesystem_path):
files = []
@@ -286,7 +285,6 @@ class SendBaseModeWeb:
"filename*": "UTF-8''%s" % url_quote(basename),
}
r.headers.set("Content-Disposition", "inline", **filename_dict)
- r = self.web.add_security_headers(r)
(content_type, _) = mimetypes.guess_type(basename, strict=False)
if content_type is not None:
r.headers.set("Content-Type", content_type)
diff --git a/cli/onionshare_cli/web/share_mode.py b/cli/onionshare_cli/web/share_mode.py
index 51ddd674..8ac4055e 100644
--- a/cli/onionshare_cli/web/share_mode.py
+++ b/cli/onionshare_cli/web/share_mode.py
@@ -25,7 +25,7 @@ import sys
import tempfile
import zipfile
import mimetypes
-from datetime import datetime
+from datetime import datetime, timezone
from flask import Response, request, render_template, make_response, abort
from unidecode import unidecode
from werkzeug.http import parse_date, http_date
@@ -127,7 +127,7 @@ class ShareModeWeb(SendBaseModeWeb):
self.download_etag = None
self.gzip_etag = None
- self.last_modified = datetime.utcnow()
+ self.last_modified = datetime.now(tz=timezone.utc)
def define_routes(self):
"""
@@ -149,8 +149,7 @@ class ShareModeWeb(SendBaseModeWeb):
and self.download_in_progress
)
if deny_download:
- r = make_response(render_template("denied.html"))
- return self.web.add_security_headers(r)
+ return render_template("denied.html")
# If download is allowed to continue, serve download page
if self.should_use_gzip():
@@ -172,8 +171,7 @@ class ShareModeWeb(SendBaseModeWeb):
and self.download_in_progress
)
if deny_download:
- r = make_response(render_template("denied.html"))
- return self.web.add_security_headers(r)
+ return render_template("denied.html")
# Prepare some variables to use inside generate() function below
# which is outside of the request context
@@ -232,7 +230,6 @@ class ShareModeWeb(SendBaseModeWeb):
"filename*": "UTF-8''%s" % url_quote(basename),
}
r.headers.set("Content-Disposition", "attachment", **filename_dict)
- r = self.web.add_security_headers(r)
# guess content type
(content_type, _) = mimetypes.guess_type(basename, strict=False)
if content_type is not None:
@@ -288,6 +285,8 @@ class ShareModeWeb(SendBaseModeWeb):
if_unmod = request.headers.get("If-Unmodified-Since")
if if_unmod:
if_date = parse_date(if_unmod)
+ if if_date and not if_date.tzinfo:
+ if_date = if_date.replace(tzinfo=timezone.utc) # Compatible with Flask < 2.0.0
if if_date and if_date > last_modified:
abort(412)
elif range_header is None:
diff --git a/cli/onionshare_cli/web/web.py b/cli/onionshare_cli/web/web.py
index 0f2dfe7e..e12fccc7 100644
--- a/cli/onionshare_cli/web/web.py
+++ b/cli/onionshare_cli/web/web.py
@@ -191,6 +191,21 @@ class Web:
Common web app routes between all modes.
"""
+ @self.app.after_request
+ def add_security_headers(r):
+ """
+ Add security headers to a response
+ """
+ for header, value in self.security_headers:
+ r.headers.set(header, value)
+ # Set a CSP header unless in website mode and the user has disabled it
+ if not self.settings.get("website", "disable_csp") or self.mode != "website":
+ r.headers.set(
+ "Content-Security-Policy",
+ "default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; img-src 'self' data:;",
+ )
+ return r
+
@self.app.errorhandler(404)
def not_found(e):
mode = self.get_mode()
@@ -232,10 +247,7 @@ class Web:
def error403(self):
self.add_request(Web.REQUEST_OTHER, request.path)
- r = make_response(
- render_template("403.html", static_url_path=self.static_url_path), 403
- )
- return self.add_security_headers(r)
+ return render_template("403.html", static_url_path=self.static_url_path), 403
def error404(self, history_id):
mode = self.get_mode()
@@ -247,10 +259,7 @@ class Web:
)
self.add_request(Web.REQUEST_OTHER, request.path)
- r = make_response(
- render_template("404.html", static_url_path=self.static_url_path), 404
- )
- return self.add_security_headers(r)
+ return render_template("404.html", static_url_path=self.static_url_path), 404
def error405(self, history_id):
mode = self.get_mode()
@@ -262,10 +271,7 @@ class Web:
)
self.add_request(Web.REQUEST_OTHER, request.path)
- r = make_response(
- render_template("405.html", static_url_path=self.static_url_path), 405
- )
- return self.add_security_headers(r)
+ return render_template("405.html", static_url_path=self.static_url_path), 405
def error500(self, history_id):
mode = self.get_mode()
@@ -277,24 +283,7 @@ class Web:
)
self.add_request(Web.REQUEST_OTHER, request.path)
- r = make_response(
- render_template("500.html", static_url_path=self.static_url_path), 500
- )
- return self.add_security_headers(r)
-
- def add_security_headers(self, r):
- """
- Add security headers to a request
- """
- for header, value in self.security_headers:
- r.headers.set(header, value)
- # Set a CSP header unless in website mode and the user has disabled it
- if not self.settings.get("website", "disable_csp") or self.mode != "website":
- r.headers.set(
- "Content-Security-Policy",
- "default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; img-src 'self' data:;",
- )
- return r
+ return render_template("500.html", static_url_path=self.static_url_path), 500
def _safe_select_jinja_autoescape(self, filename):
if filename is None:
@@ -372,9 +361,18 @@ class Web:
# To stop flask, load http://shutdown:[shutdown_password]@127.0.0.1/[shutdown_password]/shutdown
# (We're putting the shutdown_password in the path as well to make routing simpler)
if self.running:
- requests.get(
- f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown"
- )
+ try:
+ requests.get(
+ f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown"
+ )
+ except requests.exceptions.ConnectionError as e:
+ # The way flask-socketio stops a connection when running using
+ # eventlet is by raising SystemExit to abort all the processes.
+ # Hence the connections are closed and no response is returned
+ # to the above request. So I am just catching the ConnectionError
+ # to check if it was chat mode, in which case it's okay
+ if self.mode != "chat":
+ raise e
def cleanup(self):
"""
diff --git a/cli/tests/test_cli_common.py b/cli/tests/test_cli_common.py
index 3288e52b..9f113a84 100644
--- a/cli/tests/test_cli_common.py
+++ b/cli/tests/test_cli_common.py
@@ -169,7 +169,7 @@ class TestGetTorPaths:
obfs4proxy_file_path,
)
- @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux")
+ @pytest.mark.skipif(sys.platform != "linux", reason="requires Linux")
def test_get_tor_paths_linux(self, platform_linux, common_obj):
(
tor_path,
diff --git a/cli/tests/test_cli_settings.py b/cli/tests/test_cli_settings.py
index 4c012901..ed8d5bb9 100644
--- a/cli/tests/test_cli_settings.py
+++ b/cli/tests/test_cli_settings.py
@@ -123,7 +123,7 @@ class TestSettings:
"~/Library/Application Support/OnionShare-testdata/onionshare.json"
)
- @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux")
+ @pytest.mark.skipif(sys.platform != "linux", reason="requires Linux")
def test_filename_linux(self, monkeypatch, platform_linux):
obj = settings.Settings(common.Common())
assert obj.filename == os.path.expanduser(
diff --git a/cli/tests/test_cli_web.py b/cli/tests/test_cli_web.py
index f2b1af62..71bfeeeb 100644
--- a/cli/tests/test_cli_web.py
+++ b/cli/tests/test_cli_web.py
@@ -569,7 +569,7 @@ class TestRangeRequests:
assert resp.status_code == 206
- @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux")
+ @pytest.mark.skipif(sys.platform != "linux", reason="requires Linux")
@check_unsupported("curl", ["--version"])
def test_curl(self, temp_dir, tmpdir, common_obj):
web = web_obj(temp_dir, common_obj, "share", 3)
@@ -591,7 +591,7 @@ class TestRangeRequests:
]
)
- @pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux")
+ @pytest.mark.skipif(sys.platform != "linux", reason="requires Linux")
@check_unsupported("wget", ["--version"])
def test_wget(self, temp_dir, tmpdir, common_obj):
web = web_obj(temp_dir, common_obj, "share", 3)
diff --git a/desktop/src/onionshare/resources/locale/ar.json b/desktop/src/onionshare/resources/locale/ar.json
index 83e88c28..d5bdc9fe 100644
--- a/desktop/src/onionshare/resources/locale/ar.json
+++ b/desktop/src/onionshare/resources/locale/ar.json
@@ -230,7 +230,7 @@
"gui_settings_website_label": "اعدادات الموقع",
"gui_receive_flatpak_data_dir": "بسبب أنت قد ثبّت OnionShare باستخدام Flatpak، يجب عليك حفظ الملفات داخل مُجلد في المسار ~/OnionShare.",
"gui_qr_code_dialog_title": "OnionShare رمز الاستجابة السريعة",
- "gui_show_url_qr_code": "إظهار رمز الاستجابة السريعة",
+ "gui_show_qr_code": "إظهار رمز الاستجابة السريعة",
"gui_chat_stop_server": "إيقاف خادم الدردشة",
"gui_chat_start_server": "ابدأ خادم الدردشة",
"gui_file_selection_remove_all": "إزالة الكُل",
diff --git a/desktop/src/onionshare/resources/locale/bn.json b/desktop/src/onionshare/resources/locale/bn.json
index 0f87ef3f..5ae4e081 100644
--- a/desktop/src/onionshare/resources/locale/bn.json
+++ b/desktop/src/onionshare/resources/locale/bn.json
@@ -269,7 +269,7 @@
"gui_tab_name_receive": "গ্রহণ",
"gui_tab_name_share": "শেয়ার",
"gui_qr_code_dialog_title": "অনিওনশেয়ার কিউআর কোড",
- "gui_show_url_qr_code": "কিউআর কোড দেখাও",
+ "gui_show_qr_code": "কিউআর কোড দেখাও",
"gui_receive_flatpak_data_dir": "যেহেতু অনিওনশেয়ার ফ্ল্যাটপ্যাক দিয়ে ইন্সটল করেছো, তাই তোমাকে ~/OnionShare এ ফাইল সংরক্ষণ করতে হবে।",
"gui_rendezvous_cleanup": "তোমার ফাইলগুলি সফলভাবে স্থানান্তরিত হয়েছে তা নিশ্চিত হয়ে টর সার্কিট বন্ধের অপেক্ষা করা হচ্ছে।\n\nএটি কয়েক মিনিট সময় নিতে পারে।",
"gui_open_folder_error": "xdg-open দিয়ে ফোল্ডার খুলতে ব্যর্থ হয়েছে। ফাইলটি এখানে: {}",
diff --git a/desktop/src/onionshare/resources/locale/ca.json b/desktop/src/onionshare/resources/locale/ca.json
index 6eb57f3b..132c764a 100644
--- a/desktop/src/onionshare/resources/locale/ca.json
+++ b/desktop/src/onionshare/resources/locale/ca.json
@@ -267,7 +267,7 @@
"gui_new_tab_share_description": "Trieu els fitxers del vostre ordinador que voleu enviar a algú altre. La persona a qui voleu enviar els fitxers haurà d'usar el navegador Tor per a baixar-los del vostre equip.",
"gui_qr_code_description": "Escanegeu aquest codi amb un lector de QR, com ara la càmera del telèfon, per a facilitar la compartició de l'adreça de l'OnionShare amb altres.",
"gui_qr_code_dialog_title": "Codi QR de l'OnionShare",
- "gui_show_url_qr_code": "Mostra el codi QR",
+ "gui_show_qr_code": "Mostra el codi QR",
"gui_receive_flatpak_data_dir": "Com que heu instal·lat l'OnionShare amb el Flatpak, heu de desar els fitxers en una carpeta dins ~/OnionShare.",
"gui_chat_stop_server": "Atura el servidor de xat",
"gui_chat_start_server": "Inicia el servidor de xat",
diff --git a/desktop/src/onionshare/resources/locale/ckb.json b/desktop/src/onionshare/resources/locale/ckb.json
index 8289918c..68122adb 100644
--- a/desktop/src/onionshare/resources/locale/ckb.json
+++ b/desktop/src/onionshare/resources/locale/ckb.json
@@ -27,7 +27,7 @@
"gui_canceled": "Betal bû",
"gui_copied_url_title": "Malpera OnionShare kopî bû",
"gui_copied_url": "Malpera OnionShare lis ser taxtê kopî bû",
- "gui_show_url_qr_code": "QR kod nîşan bide",
+ "gui_show_qr_code": "QR kod nîşan bide",
"gui_qr_code_dialog_title": "OnionShare QR kod",
"gui_waiting_to_start": "Pilankirî ye di {} destpê bike. Bitkîne ji bo betal bike.",
"gui_please_wait": "Destpê dike...Bitikîne ji bo betal bike.",
diff --git a/desktop/src/onionshare/resources/locale/da.json b/desktop/src/onionshare/resources/locale/da.json
index d24f70e7..57ff605a 100644
--- a/desktop/src/onionshare/resources/locale/da.json
+++ b/desktop/src/onionshare/resources/locale/da.json
@@ -269,7 +269,7 @@
"gui_open_folder_error": "Kunne ikke åbne mappen med xdg-open. Filen er her: {}",
"gui_qr_code_description": "Skan QR-koden med en QR-læser såsom kameraet i din telefon for at gøre det lettere at dele OnionShare-adressen med andre.",
"gui_qr_code_dialog_title": "QR-kode til OnionShare",
- "gui_show_url_qr_code": "Vis QR-kode",
+ "gui_show_qr_code": "Vis QR-kode",
"gui_receive_flatpak_data_dir": "Da du installerede OnionShare med Flatpak, så skal du gemme filer til en mappe i ~/OnionShare.",
"gui_chat_stop_server": "Stop chatserver",
"gui_chat_start_server": "Start chatserver",
diff --git a/desktop/src/onionshare/resources/locale/de.json b/desktop/src/onionshare/resources/locale/de.json
index 518a7113..c6cb7731 100644
--- a/desktop/src/onionshare/resources/locale/de.json
+++ b/desktop/src/onionshare/resources/locale/de.json
@@ -273,7 +273,7 @@
"gui_remove": "Entfernen",
"gui_new_tab_chat_button": "Anonym chatten",
"gui_qr_code_dialog_title": "OnionShare QR-Code",
- "gui_show_url_qr_code": "QR-Code anzeigen",
+ "gui_show_qr_code": "QR-Code anzeigen",
"gui_chat_stop_server": "Chatserver stoppen",
"gui_chat_start_server": "Chatserver starten",
"gui_main_page_chat_button": "Chat starten",
diff --git a/desktop/src/onionshare/resources/locale/el.json b/desktop/src/onionshare/resources/locale/el.json
index 25649b4b..41cbdf82 100644
--- a/desktop/src/onionshare/resources/locale/el.json
+++ b/desktop/src/onionshare/resources/locale/el.json
@@ -273,7 +273,7 @@
"gui_new_tab_tooltip": "Άνοιγμα νέας καρτέλας",
"gui_new_tab": "Νέα καρτέλα",
"gui_qr_code_dialog_title": "Κώδικας QR OnionShare",
- "gui_show_url_qr_code": "Προβολή κώδικα QR",
+ "gui_show_qr_code": "Προβολή κώδικα QR",
"gui_file_selection_remove_all": "Αφαίρεση όλων",
"gui_remove": "Αφαίρεση",
"error_port_not_available": "Η θύρα OnionShare δεν είναι διαθέσιμη",
diff --git a/desktop/src/onionshare/resources/locale/en.json b/desktop/src/onionshare/resources/locale/en.json
index e7eba1cb..03694947 100644
--- a/desktop/src/onionshare/resources/locale/en.json
+++ b/desktop/src/onionshare/resources/locale/en.json
@@ -30,10 +30,12 @@
"gui_copied_url": "OnionShare address copied to clipboard",
"gui_copied_client_auth_title": "Copied Private Key",
"gui_copied_client_auth": "Private Key copied to clipboard",
- "gui_show_url_qr_code": "Show QR Code",
+ "gui_show_qr_code": "Show QR Code",
"gui_qr_code_dialog_title": "OnionShare QR Code",
"gui_qr_label_url_title": "OnionShare Address",
"gui_qr_label_auth_string_title": "Private Key",
+ "gui_reveal": "Reveal",
+ "gui_hide": "Hide",
"gui_waiting_to_start": "Scheduled to start in {}. Click to cancel.",
"gui_please_wait_no_button": "Starting…",
"gui_please_wait": "Starting… Click to cancel.",
@@ -100,6 +102,9 @@
"gui_url_label_stay_open": "This share will not auto-stop.",
"gui_url_label_onetime": "This share will stop after first completion.",
"gui_url_label_onetime_and_persistent": "This share will not auto-stop.<br><br>Every subsequent share will reuse the address. (To use one-time addresses, turn off \"Use persistent address\" in the settings.)",
+ "gui_url_instructions": "First, send the OnionShare address below:",
+ "gui_url_instructions_public_mode": "Send the OnionShare address below:",
+ "gui_client_auth_instructions": "Next, send the private key to allow access to your OnionShare service:",
"gui_status_indicator_share_stopped": "Ready to share",
"gui_status_indicator_share_working": "Starting…",
"gui_status_indicator_share_scheduled": "Scheduled…",
@@ -211,4 +216,4 @@
"error_port_not_available": "OnionShare port not available",
"history_receive_read_message_button": "Read Message",
"error_tor_protocol_error": "There was an error with Tor: {}"
-}
+} \ No newline at end of file
diff --git a/desktop/src/onionshare/resources/locale/es.json b/desktop/src/onionshare/resources/locale/es.json
index 7b04a9e2..c9efc51a 100644
--- a/desktop/src/onionshare/resources/locale/es.json
+++ b/desktop/src/onionshare/resources/locale/es.json
@@ -277,7 +277,7 @@
"gui_open_folder_error": "Fallo al abrir carpeta con xdg-open. El archivo está aquí: {}",
"gui_qr_code_description": "Escanea este código QR con un lector QR, como la cámara de tu teléfono para compartir la dirección OnionShare.",
"gui_qr_code_dialog_title": "Código QR de OnionShare",
- "gui_show_url_qr_code": "Mostrar Código QR",
+ "gui_show_qr_code": "Mostrar Código QR",
"gui_receive_flatpak_data_dir": "Al instalar OnionShare usando Flatpak, debes guardar los archivos en una carpeta en ~/OnionShare.",
"gui_chat_stop_server": "Detener servidor de chat",
"gui_chat_start_server": "Iniciar servidor de chat",
diff --git a/desktop/src/onionshare/resources/locale/fi.json b/desktop/src/onionshare/resources/locale/fi.json
index 25fd2a94..37c28dac 100644
--- a/desktop/src/onionshare/resources/locale/fi.json
+++ b/desktop/src/onionshare/resources/locale/fi.json
@@ -258,7 +258,7 @@
"gui_chat_url_description": "<b>Kuka tahansa</b> tällä Onionshare-osoitteella voi <b>liittyä tähän keskusteluryhmään</b> käyttämällä <b>Tor-selainta</b>: <img src='{}' />",
"gui_please_wait_no_button": "Aloitetaan…",
"gui_qr_code_dialog_title": "OnionSharen QR-koodi",
- "gui_show_url_qr_code": "Näytä QR-koodi",
+ "gui_show_qr_code": "Näytä QR-koodi",
"gui_receive_flatpak_data_dir": "Koska asensin OnionSharen käyttämällä Flatpakia, sinun täytyy tallentaa tiedostot kansioon sijainnissa ~/OnionShare.",
"gui_chat_stop_server": "Pysäytä chat-palvelin",
"gui_chat_start_server": "Perusta chat-palvelin"
diff --git a/desktop/src/onionshare/resources/locale/fr.json b/desktop/src/onionshare/resources/locale/fr.json
index 5ac2c6d0..3bb2c838 100644
--- a/desktop/src/onionshare/resources/locale/fr.json
+++ b/desktop/src/onionshare/resources/locale/fr.json
@@ -272,7 +272,7 @@
"gui_open_folder_error": "Échec d’ouverture du dossier avec xdg-open. Le fichier est ici : {}",
"gui_qr_code_description": "Balayez ce code QR avec un lecteur de code QR, tel que l’appareil photo votre appareil, afin de partager plus facilement l’adresse OnionShare avec quelqu’un.",
"gui_qr_code_dialog_title": "Code QR d’OnionShare",
- "gui_show_url_qr_code": "Afficher le code QR",
+ "gui_show_qr_code": "Afficher le code QR",
"gui_receive_flatpak_data_dir": "Comme vous avez installé OnionShare grâce à Flatpak, vous devez enregistrer vos fichiers dans un sous-dossier de ~/OnionShare.",
"gui_chat_stop_server": "Arrêter le serveur de dialogue en ligne",
"gui_chat_start_server": "Démarrer le serveur de dialogue en ligne",
diff --git a/desktop/src/onionshare/resources/locale/gl.json b/desktop/src/onionshare/resources/locale/gl.json
index 758c3137..97a99ff7 100644
--- a/desktop/src/onionshare/resources/locale/gl.json
+++ b/desktop/src/onionshare/resources/locale/gl.json
@@ -27,7 +27,7 @@
"gui_canceled": "Cancelado",
"gui_copied_url_title": "Enderezo de OnionShare copiado",
"gui_copied_url": "Enderezo OnionShare copiado ó portapapeis",
- "gui_show_url_qr_code": "Mostrar código QR",
+ "gui_show_qr_code": "Mostrar código QR",
"gui_qr_code_dialog_title": "Código QR OnionShare",
"gui_waiting_to_start": "Programado para comezar en {}. Fai clic para cancelar.",
"gui_please_wait": "Iniciando... Fai click para cancelar.",
diff --git a/desktop/src/onionshare/resources/locale/hi.json b/desktop/src/onionshare/resources/locale/hi.json
index 7cc230c8..9351bc6b 100644
--- a/desktop/src/onionshare/resources/locale/hi.json
+++ b/desktop/src/onionshare/resources/locale/hi.json
@@ -181,7 +181,7 @@
"incorrect_password": "पासवर्ड गलत है",
"gui_settings_individual_downloads_label": "विशिष्ट फाइलों के डाउनलोड को मंजूरी देने के लिए अचिन्हित करें",
"gui_settings_csp_header_disabled_option": "सामग्री सुरक्षा नियम हेडर को अक्षम करें",
- "gui_show_url_qr_code": "क्यूआर कोड दिखाएं",
+ "gui_show_qr_code": "क्यूआर कोड दिखाएं",
"gui_chat_stop_server": "चैट सर्वर बंद करें",
"gui_chat_start_server": "चैट सर्वर शुरू करें",
"gui_file_selection_remove_all": "सभी हटाएं",
diff --git a/desktop/src/onionshare/resources/locale/hr.json b/desktop/src/onionshare/resources/locale/hr.json
index efc24f4e..c49e01d2 100644
--- a/desktop/src/onionshare/resources/locale/hr.json
+++ b/desktop/src/onionshare/resources/locale/hr.json
@@ -215,7 +215,7 @@
"gui_tab_name_website": "Web-stranica",
"gui_tab_name_share": "Dijeli",
"gui_qr_code_dialog_title": "OnionShare QR-kod",
- "gui_show_url_qr_code": "Prikaži QR-kod",
+ "gui_show_qr_code": "Prikaži QR-kod",
"gui_file_selection_remove_all": "Ukloni sve",
"gui_remove": "Ukloni",
"gui_main_page_chat_button": "Pokreni razgovor",
diff --git a/desktop/src/onionshare/resources/locale/id.json b/desktop/src/onionshare/resources/locale/id.json
index 55af7794..36b8c41a 100644
--- a/desktop/src/onionshare/resources/locale/id.json
+++ b/desktop/src/onionshare/resources/locale/id.json
@@ -248,7 +248,7 @@
"systray_share_started_title": "Berbagi dimulai",
"gui_color_mode_changed_notice": "Mulai ulang OnionShare agar mode warna baru diterapkan.",
"gui_qr_code_dialog_title": "Kode QR OnionShare",
- "gui_show_url_qr_code": "Tampilkan kode QR",
+ "gui_show_qr_code": "Tampilkan kode QR",
"error_port_not_available": "Port OnionShare tidak tersedia",
"gui_chat_stop_server": "Hentikan server obrolan",
"gui_chat_start_server": "Mulai server obrolan",
diff --git a/desktop/src/onionshare/resources/locale/is.json b/desktop/src/onionshare/resources/locale/is.json
index 91600653..c5f206df 100644
--- a/desktop/src/onionshare/resources/locale/is.json
+++ b/desktop/src/onionshare/resources/locale/is.json
@@ -270,7 +270,7 @@
"gui_chat_stop_server_autostop_timer": "Stöðva spjallþjón ({})",
"gui_qr_code_dialog_title": "QR-kóði OnionShare",
"gui_file_selection_remove_all": "Fjarlægja allt",
- "gui_show_url_qr_code": "Birta QR-kóða",
+ "gui_show_qr_code": "Birta QR-kóða",
"gui_new_tab_chat_button": "Spjalla nafnlaust",
"gui_main_page_chat_button": "Hefja spjall",
"gui_main_page_website_button": "Hefja hýsingu",
diff --git a/desktop/src/onionshare/resources/locale/it.json b/desktop/src/onionshare/resources/locale/it.json
index 56463b14..9063f0f0 100644
--- a/desktop/src/onionshare/resources/locale/it.json
+++ b/desktop/src/onionshare/resources/locale/it.json
@@ -245,7 +245,7 @@
"gui_new_tab": "Nuova Scheda",
"gui_open_folder_error": "Impossibile aprire la cartella con xdg-open. Il file è qui: {}",
"gui_qr_code_dialog_title": "OnionShare QR Code",
- "gui_show_url_qr_code": "Mostra QR Code",
+ "gui_show_qr_code": "Mostra QR Code",
"gui_receive_flatpak_data_dir": "Dato che hai installato OnionShare usando Flatpak, devi salvare i file nella cartella ~/OnionShare.",
"gui_chat_stop_server": "Arresta il server della chat",
"gui_file_selection_remove_all": "Rimuovi tutto",
diff --git a/desktop/src/onionshare/resources/locale/ja.json b/desktop/src/onionshare/resources/locale/ja.json
index 6f7d0cff..3d20f966 100644
--- a/desktop/src/onionshare/resources/locale/ja.json
+++ b/desktop/src/onionshare/resources/locale/ja.json
@@ -266,7 +266,7 @@
"gui_open_folder_error": "xdg-openでフォルダー開くの失敗。ファイルはここにあります: {}",
"gui_qr_code_description": "より簡単にOnionShareアドレスを共有するため、スマホのカメラなどのQRリーダーでこのコードをスキャンして下さい。",
"gui_qr_code_dialog_title": "OnionShareのQRコード",
- "gui_show_url_qr_code": "QRコードを表示",
+ "gui_show_qr_code": "QRコードを表示",
"gui_receive_flatpak_data_dir": "FlatpakでOnionShareをインストールしたため、ファイルを~/OnionShareの中のフォルダーに保存しなければなりません。",
"gui_chat_stop_server": "チャットサーバーを停止",
"gui_chat_start_server": "チャットサーバーを始動",
diff --git a/desktop/src/onionshare/resources/locale/lt.json b/desktop/src/onionshare/resources/locale/lt.json
index 0623a8b1..8c88f066 100644
--- a/desktop/src/onionshare/resources/locale/lt.json
+++ b/desktop/src/onionshare/resources/locale/lt.json
@@ -205,7 +205,7 @@
"gui_file_selection_remove_all": "Šalinti visus",
"gui_remove": "Šalinti",
"gui_qr_code_dialog_title": "OnionShare QR kodas",
- "gui_show_url_qr_code": "Rodyti QR kodą",
+ "gui_show_qr_code": "Rodyti QR kodą",
"gui_open_folder_error": "Nepavyko atverti aplanko naudojant xdg-open. Failas yra čia: {}",
"gui_chat_stop_server": "Sustabdyti pokalbių serverį",
"gui_chat_start_server": "Pradėti pokalbių serverį",
diff --git a/desktop/src/onionshare/resources/locale/nb_NO.json b/desktop/src/onionshare/resources/locale/nb_NO.json
index 33825216..8ab21432 100644
--- a/desktop/src/onionshare/resources/locale/nb_NO.json
+++ b/desktop/src/onionshare/resources/locale/nb_NO.json
@@ -279,7 +279,7 @@
"gui_new_tab_chat_button": "Sludre anonymt",
"gui_qr_code_description": "Skann denne QR-koden med en QR-kodeleser (f.eks. kameraprogrammet på enheten din) for enklere deling av OnionShare-adressen med noen.",
"gui_qr_code_dialog_title": "OnionShare-QR-kode",
- "gui_show_url_qr_code": "Vis QR-kode",
+ "gui_show_qr_code": "Vis QR-kode",
"gui_main_page_chat_button": "Start sludring",
"gui_main_page_website_button": "Start vertsjening",
"gui_main_page_receive_button": "Start mottak",
diff --git a/desktop/src/onionshare/resources/locale/nl.json b/desktop/src/onionshare/resources/locale/nl.json
index ed70622a..2ae1351a 100644
--- a/desktop/src/onionshare/resources/locale/nl.json
+++ b/desktop/src/onionshare/resources/locale/nl.json
@@ -274,7 +274,7 @@
"gui_new_tab": "Nieuw tabblad",
"gui_open_folder_error": "Niet gelukt om de map te openen met xdg-open. Het bestand staat hier: {}",
"gui_qr_code_dialog_title": "OnionShare QR Code",
- "gui_show_url_qr_code": "Toon QR Code",
+ "gui_show_qr_code": "Toon QR Code",
"gui_receive_flatpak_data_dir": "Omdat je OnionShare installeerde met Flatpak, moet je bestanden opslaan in een folder in ~/OnionShare.",
"gui_chat_stop_server": "Stop chat server",
"gui_chat_start_server": "Start chat server",
diff --git a/desktop/src/onionshare/resources/locale/pl.json b/desktop/src/onionshare/resources/locale/pl.json
index 1a2f17a6..f8c2bc53 100644
--- a/desktop/src/onionshare/resources/locale/pl.json
+++ b/desktop/src/onionshare/resources/locale/pl.json
@@ -246,7 +246,7 @@
"gui_open_folder_error": "Nie udało się otworzyć folderu za pomocą xdg-open. Plik jest tutaj: {}",
"gui_qr_code_description": "Zeskanuj ten kod QR za pomocą czytnika QR, takiego jak aparat w telefonie, aby łatwiej udostępnić komuś adres OnionShare.",
"gui_qr_code_dialog_title": "Kod QR OnionShare",
- "gui_show_url_qr_code": "Pokaż kod QR",
+ "gui_show_qr_code": "Pokaż kod QR",
"gui_receive_flatpak_data_dir": "Ponieważ zainstalowałeś OnionShare przy użyciu Flatpak, musisz zapisywać pliki w folderze w ~ / OnionShare.",
"gui_chat_stop_server": "Zatrzymaj serwer czatu",
"gui_chat_start_server": "Uruchom serwer czatu",
diff --git a/desktop/src/onionshare/resources/locale/pt_BR.json b/desktop/src/onionshare/resources/locale/pt_BR.json
index ebbef428..07e6c7d2 100644
--- a/desktop/src/onionshare/resources/locale/pt_BR.json
+++ b/desktop/src/onionshare/resources/locale/pt_BR.json
@@ -269,7 +269,7 @@
"gui_open_folder_error": "Falha ao abrir a pasta com xdg-open. O arquivo está aqui: {}",
"gui_qr_code_description": "Leia este código QR com um leitor, como a câmera do seu celular, para compartilhar mais facilmente o endereço OnionShare com alguém.",
"gui_qr_code_dialog_title": "Código QR OnionShare",
- "gui_show_url_qr_code": "Mostrar código QR",
+ "gui_show_qr_code": "Mostrar código QR",
"gui_receive_flatpak_data_dir": "Como você instalou o OnionShare usando o Flatpak, você deve salvar os arquivos em uma pasta em ~ / OnionShare.",
"gui_chat_stop_server": "Parar o servidor de conversas",
"gui_chat_start_server": "Iniciar um servidor de conversas",
diff --git a/desktop/src/onionshare/resources/locale/pt_PT.json b/desktop/src/onionshare/resources/locale/pt_PT.json
index a699a5f3..f5b092c3 100644
--- a/desktop/src/onionshare/resources/locale/pt_PT.json
+++ b/desktop/src/onionshare/resources/locale/pt_PT.json
@@ -267,7 +267,7 @@
"gui_new_tab_chat_button": "Converse Anónimamente",
"gui_open_folder_error": "Falhou a abrir a pasta com xdc-open. O ficheiro está aqui: {}",
"gui_qr_code_dialog_title": "OnionShare Código QR",
- "gui_show_url_qr_code": "Mostrar código QR",
+ "gui_show_qr_code": "Mostrar código QR",
"gui_receive_flatpak_data_dir": "Como instalou o OnionShare utilizando Flatpak, deve guardar os ficheiros na pasta ~/OnionShare.",
"gui_chat_stop_server": "Para servidor de conversa",
"gui_chat_start_server": "Começar servidor de conversa",
diff --git a/desktop/src/onionshare/resources/locale/ru.json b/desktop/src/onionshare/resources/locale/ru.json
index 967e87b6..a3b57fb4 100644
--- a/desktop/src/onionshare/resources/locale/ru.json
+++ b/desktop/src/onionshare/resources/locale/ru.json
@@ -266,7 +266,7 @@
"gui_open_folder_error": "Ошибка при попытке открыть папку с помощью xdg-open. Файл находится здесь: {}",
"gui_qr_code_description": "Сканируйте этот QR-код считывающим устройством, например камерой Вашего телефона, чтобы было удобнее поделиться ссылкой OnionShare с кем либо.",
"gui_qr_code_dialog_title": "Код QR OnionShare",
- "gui_show_url_qr_code": "Показать код QR",
+ "gui_show_qr_code": "Показать код QR",
"gui_receive_flatpak_data_dir": "Так как Вы установили OnionShare с помощью Flatpak, Вы должны сохранять файлы в папке ~/OnionShare.",
"gui_chat_stop_server": "Остановить сервер чата",
"gui_chat_start_server": "Запустить сервер чата",
diff --git a/desktop/src/onionshare/resources/locale/si.json b/desktop/src/onionshare/resources/locale/si.json
index cb15cc72..32417022 100644
--- a/desktop/src/onionshare/resources/locale/si.json
+++ b/desktop/src/onionshare/resources/locale/si.json
@@ -27,7 +27,7 @@
"gui_canceled": "",
"gui_copied_url_title": "",
"gui_copied_url": "",
- "gui_show_url_qr_code": "",
+ "gui_show_qr_code": "",
"gui_qr_code_dialog_title": "",
"gui_waiting_to_start": "",
"gui_please_wait": "",
diff --git a/desktop/src/onionshare/resources/locale/sk.json b/desktop/src/onionshare/resources/locale/sk.json
index 8ee83a28..841b156e 100644
--- a/desktop/src/onionshare/resources/locale/sk.json
+++ b/desktop/src/onionshare/resources/locale/sk.json
@@ -27,7 +27,7 @@
"gui_canceled": "Zrušené",
"gui_copied_url_title": "Skopírovaná OnionShare adresa",
"gui_copied_url": "OnionShare adresa bola skopírovaná do schránky",
- "gui_show_url_qr_code": "Zobraziť QR kód",
+ "gui_show_qr_code": "Zobraziť QR kód",
"gui_qr_code_dialog_title": "OnionShare QR kód",
"gui_qr_code_description": "Naskenujte tento QR kód pomocou čítačky QR, napríklad fotoaparátom na telefóne, aby ste mohli jednoduchšie zdieľať adresu OnionShare s niekým.",
"gui_waiting_to_start": "Naplánované spustenie o {}. Kliknutím zrušíte.",
diff --git a/desktop/src/onionshare/resources/locale/sr_Latn.json b/desktop/src/onionshare/resources/locale/sr_Latn.json
index da986f48..0241a140 100644
--- a/desktop/src/onionshare/resources/locale/sr_Latn.json
+++ b/desktop/src/onionshare/resources/locale/sr_Latn.json
@@ -216,7 +216,7 @@
"gui_open_folder_error": "Neuspelo otvaranje fascikle sa xdg-open. Fajl je ovde: {}",
"gui_chat_url_description": "<b>Bilo ko</b> sa ovom OnionShare adresom može <b>pristupiti ovoj sobi za ćaskawe</b> koristeći <b>Tor pregledač</b>: <img src='{}' />",
"gui_qr_code_dialog_title": "OnionShare QR kod",
- "gui_show_url_qr_code": "Prikaži QR kod",
+ "gui_show_qr_code": "Prikaži QR kod",
"gui_receive_flatpak_data_dir": "Pošto ste instalirali OnionShare koristeći Flatpak, morate čuvati fajlove u falcikli ~/OnionShare.",
"gui_chat_stop_server": "Zaustavi server za ćaskanje",
"gui_chat_start_server": "Pokreni server za ćaskanje",
diff --git a/desktop/src/onionshare/resources/locale/sv.json b/desktop/src/onionshare/resources/locale/sv.json
index 302166f1..f982d200 100644
--- a/desktop/src/onionshare/resources/locale/sv.json
+++ b/desktop/src/onionshare/resources/locale/sv.json
@@ -266,7 +266,7 @@
"gui_new_tab": "Ny flik",
"gui_qr_code_description": "Skanna den här QR-koden med en QR-läsare, till exempel kameran på din telefon, för att lättare kunna dela OnionShare-adressen med någon.",
"gui_qr_code_dialog_title": "OnionShare QR-kod",
- "gui_show_url_qr_code": "Visa QR-kod",
+ "gui_show_qr_code": "Visa QR-kod",
"gui_receive_flatpak_data_dir": "Eftersom du installerade OnionShare med Flatpak måste du spara filer i en mapp i ~/OnionShare.",
"gui_chat_stop_server": "Stoppa chattservern",
"gui_chat_start_server": "Starta chattservern",
diff --git a/desktop/src/onionshare/resources/locale/tr.json b/desktop/src/onionshare/resources/locale/tr.json
index d8a34d02..b86dd39c 100644
--- a/desktop/src/onionshare/resources/locale/tr.json
+++ b/desktop/src/onionshare/resources/locale/tr.json
@@ -233,7 +233,7 @@
"gui_chat_start_server": "Sohbet sunucusunu başlat",
"gui_chat_stop_server": "Sohbet sunucusunu durdur",
"gui_receive_flatpak_data_dir": "OnionShare'i Flatpak kullanarak kurduğunuz için, dosyaları ~/OnionShare içindeki bir klasöre kaydetmelisiniz.",
- "gui_show_url_qr_code": "QR Kodu Göster",
+ "gui_show_qr_code": "QR Kodu Göster",
"gui_qr_code_dialog_title": "OnionShare QR Kodu",
"gui_qr_code_description": "OnionShare adresini bir başkasıyla daha kolay paylaşmak için bu QR kodunu telefonunuzdaki kamera gibi bir QR okuyucuyla tarayın.",
"gui_open_folder_error": "Klasör xdg-open ile açılamadı. Dosya burada: {}",
diff --git a/desktop/src/onionshare/resources/locale/uk.json b/desktop/src/onionshare/resources/locale/uk.json
index 49762022..2a2684e2 100644
--- a/desktop/src/onionshare/resources/locale/uk.json
+++ b/desktop/src/onionshare/resources/locale/uk.json
@@ -217,7 +217,7 @@
"gui_chat_start_server": "Запустити сервер чату",
"gui_chat_stop_server_autostop_timer": "Зупинити сервер чату ({})",
"gui_qr_code_dialog_title": "QR-код OnionShare",
- "gui_show_url_qr_code": "Показати QR-код",
+ "gui_show_qr_code": "Показати QR-код",
"gui_main_page_share_button": "Поділитися",
"gui_main_page_chat_button": "Почати спілкуватися в чаті",
"gui_main_page_website_button": "Почати хостинг",
diff --git a/desktop/src/onionshare/resources/locale/zh_Hans.json b/desktop/src/onionshare/resources/locale/zh_Hans.json
index 39aa5c3b..f0958614 100644
--- a/desktop/src/onionshare/resources/locale/zh_Hans.json
+++ b/desktop/src/onionshare/resources/locale/zh_Hans.json
@@ -257,7 +257,7 @@
"gui_new_tab_share_button": "共享文件",
"gui_new_tab_tooltip": "打开一个新标签",
"gui_new_tab": "新建标签",
- "gui_show_url_qr_code": "显示二维码",
+ "gui_show_qr_code": "显示二维码",
"gui_receive_flatpak_data_dir": "因为你用Flatpack安装的OnionShare,你需要把文件储存到在~/OnionShare里的一个文件夹里。",
"gui_chat_stop_server": "停止言论服务器",
"gui_chat_start_server": "开始言论服务器",
diff --git a/desktop/src/onionshare/resources/locale/zh_Hant.json b/desktop/src/onionshare/resources/locale/zh_Hant.json
index 29203837..f0a51217 100644
--- a/desktop/src/onionshare/resources/locale/zh_Hant.json
+++ b/desktop/src/onionshare/resources/locale/zh_Hant.json
@@ -254,7 +254,7 @@
"gui_main_page_share_button": "開始分享",
"gui_new_tab_website_button": "架設一個網站",
"gui_qr_code_dialog_title": "OnionShare QR Code",
- "gui_show_url_qr_code": "顯示QR Code",
+ "gui_show_qr_code": "顯示QR Code",
"gui_chat_stop_server": "停止聊天伺服器",
"gui_chat_start_server": "開啟聊天伺服器",
"gui_file_selection_remove_all": "全部移除",
diff --git a/desktop/src/onionshare/tab/mode/__init__.py b/desktop/src/onionshare/tab/mode/__init__.py
index 1e7121bb..d4f2c23a 100644
--- a/desktop/src/onionshare/tab/mode/__init__.py
+++ b/desktop/src/onionshare/tab/mode/__init__.py
@@ -252,11 +252,9 @@ class Mode(QtWidgets.QWidget):
not self.server_status.local_only
and not self.app.onion.supports_stealth
and not self.settings.get("general", "public")
- ):
- self.stop_server()
- self.start_server_error(
- strings._("gui_server_doesnt_support_stealth")
- )
+ ):
+ self.stop_server()
+ self.start_server_error(strings._("gui_server_doesnt_support_stealth"))
else:
self.common.log("Mode", "start_server", "Starting an onion thread")
self.obtain_onion_early = obtain_onion_early
diff --git a/desktop/src/onionshare/tab/mode/receive_mode/__init__.py b/desktop/src/onionshare/tab/mode/receive_mode/__init__.py
index e9f6b2ce..d5036d1d 100644
--- a/desktop/src/onionshare/tab/mode/receive_mode/__init__.py
+++ b/desktop/src/onionshare/tab/mode/receive_mode/__init__.py
@@ -183,16 +183,15 @@ class ReceiveMode(Mode):
self.main_layout.addWidget(header_label)
self.main_layout.addWidget(receive_warning)
self.main_layout.addWidget(self.primary_action, stretch=1)
- self.main_layout.addWidget(MinimumSizeWidget(525, 0))
+ self.main_layout.addWidget(self.server_status)
# Row layout
content_row = QtWidgets.QHBoxLayout()
- content_row.addLayout(self.main_layout)
+ content_row.addLayout(self.main_layout, stretch=1)
content_row.addWidget(self.image)
row_layout = QtWidgets.QVBoxLayout()
row_layout.addLayout(top_bar_layout)
row_layout.addLayout(content_row, stretch=1)
- row_layout.addWidget(self.server_status)
# Column layout
self.column_layout = QtWidgets.QHBoxLayout()
diff --git a/desktop/src/onionshare/tab/server_status.py b/desktop/src/onionshare/tab/server_status.py
index 3d4c723d..115acfd5 100644
--- a/desktop/src/onionshare/tab/server_status.py
+++ b/desktop/src/onionshare/tab/server_status.py
@@ -81,6 +81,12 @@ class ServerStatus(QtWidgets.QWidget):
self.url_description = QtWidgets.QLabel()
self.url_description.setWordWrap(True)
self.url_description.setMinimumHeight(50)
+
+ # URL sharing instructions, above the URL and Copy Address/QR Code buttons
+ self.url_instructions = QtWidgets.QLabel()
+ self.url_instructions.setWordWrap(True)
+
+ # The URL label itself
self.url = QtWidgets.QLabel()
self.url.setFont(url_font)
self.url.setWordWrap(True)
@@ -90,16 +96,16 @@ class ServerStatus(QtWidgets.QWidget):
Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard
)
+ # Copy Onion Address button
self.copy_url_button = QtWidgets.QPushButton(strings._("gui_copy_url"))
self.copy_url_button.setStyleSheet(
self.common.gui.css["server_status_url_buttons"]
)
self.copy_url_button.clicked.connect(self.copy_url)
- self.copy_client_auth_button = QtWidgets.QPushButton(
- strings._("gui_copy_client_auth")
- )
+
+ # Onion Address QR code button
self.show_url_qr_code_button = QtWidgets.QPushButton(
- strings._("gui_show_url_qr_code")
+ strings._("gui_show_qr_code")
)
self.show_url_qr_code_button.hide()
self.show_url_qr_code_button.clicked.connect(
@@ -109,22 +115,78 @@ class ServerStatus(QtWidgets.QWidget):
self.common.gui.css["server_status_url_buttons"]
)
+ # Client Auth sharing instructions, above the
+ # Copy Private Key/QR Code buttons
+ self.client_auth_instructions = QtWidgets.QLabel()
+ self.client_auth_instructions.setWordWrap(True)
+ self.client_auth_instructions.setText(strings._("gui_client_auth_instructions"))
+
+ # The private key itself
+ self.private_key = QtWidgets.QLabel()
+ self.private_key.setFont(url_font)
+ self.private_key.setWordWrap(True)
+ self.private_key.setMinimumSize(self.private_key.sizeHint())
+ self.private_key.setStyleSheet(self.common.gui.css["server_status_url"])
+ self.private_key.setTextInteractionFlags(Qt.NoTextInteraction)
+ self.private_key_hidden = True
+
+ # Copy ClientAuth button
+ self.copy_client_auth_button = QtWidgets.QPushButton(
+ strings._("gui_copy_client_auth")
+ )
self.copy_client_auth_button.setStyleSheet(
self.common.gui.css["server_status_url_buttons"]
)
self.copy_client_auth_button.clicked.connect(self.copy_client_auth)
+
+ # ClientAuth QR code button
+ self.show_client_auth_qr_code_button = QtWidgets.QPushButton(
+ strings._("gui_show_qr_code")
+ )
+ self.show_client_auth_qr_code_button.hide()
+ self.show_client_auth_qr_code_button.clicked.connect(
+ self.show_client_auth_qr_code_button_clicked
+ )
+ self.show_client_auth_qr_code_button.setStyleSheet(
+ self.common.gui.css["server_status_url_buttons"]
+ )
+
+ # ClientAuth reveal/hide toggle button
+ self.client_auth_toggle_button = QtWidgets.QPushButton(strings._("gui_reveal"))
+ self.client_auth_toggle_button.hide()
+ self.client_auth_toggle_button.clicked.connect(
+ self.client_auth_toggle_button_clicked
+ )
+ self.client_auth_toggle_button.setStyleSheet(
+ self.common.gui.css["server_status_url_buttons"]
+ )
+
+ # URL instructions layout
url_buttons_layout = QtWidgets.QHBoxLayout()
url_buttons_layout.addWidget(self.copy_url_button)
- url_buttons_layout.addWidget(self.copy_client_auth_button)
url_buttons_layout.addWidget(self.show_url_qr_code_button)
url_buttons_layout.addStretch()
url_layout = QtWidgets.QVBoxLayout()
url_layout.addWidget(self.url_description)
+ url_layout.addWidget(self.url_instructions)
url_layout.addWidget(self.url)
url_layout.addLayout(url_buttons_layout)
- # Add the widgets
+ # Private key instructions layout
+ client_auth_buttons_layout = QtWidgets.QHBoxLayout()
+ client_auth_buttons_layout.addWidget(self.copy_client_auth_button)
+ client_auth_buttons_layout.addWidget(self.show_client_auth_qr_code_button)
+ client_auth_buttons_layout.addWidget(self.client_auth_toggle_button)
+ client_auth_buttons_layout.addStretch()
+
+ client_auth_layout = QtWidgets.QVBoxLayout()
+ client_auth_layout.addWidget(self.client_auth_instructions)
+ client_auth_layout.addWidget(self.private_key)
+ client_auth_layout.addLayout(client_auth_buttons_layout)
+
+ # Add the widgets and URL/ClientAuth layouts
+ # to the main ServerStatus layout
button_layout = QtWidgets.QHBoxLayout()
button_layout.addWidget(self.server_button)
button_layout.addStretch()
@@ -132,6 +194,7 @@ class ServerStatus(QtWidgets.QWidget):
layout = QtWidgets.QVBoxLayout()
layout.addLayout(button_layout)
layout.addLayout(url_layout)
+ layout.addLayout(client_auth_layout)
self.setLayout(layout)
def set_mode(self, share_mode, file_selection=None):
@@ -227,16 +290,35 @@ class ServerStatus(QtWidgets.QWidget):
else:
self.url_description.setToolTip(strings._("gui_url_label_stay_open"))
+ if self.settings.get("general", "public"):
+ self.url_instructions.setText(strings._("gui_url_instructions_public_mode"))
+ else:
+ self.url_instructions.setText(strings._("gui_url_instructions"))
+ self.url_instructions.show()
self.url.setText(self.get_url())
self.url.show()
self.copy_url_button.show()
-
self.show_url_qr_code_button.show()
if self.settings.get("general", "public"):
+ self.client_auth_instructions.hide()
+ self.private_key.hide()
self.copy_client_auth_button.hide()
+ self.show_client_auth_qr_code_button.hide()
else:
+ self.client_auth_instructions.show()
+ if self.private_key_hidden:
+ self.private_key.setText("*" * len(self.app.auth_string))
+ self.private_key.setTextInteractionFlags(Qt.NoTextInteraction)
+ else:
+ self.private_key.setText(self.app.auth_string)
+ self.private_key.setTextInteractionFlags(
+ Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard
+ )
+ self.private_key.show()
self.copy_client_auth_button.show()
+ self.show_client_auth_qr_code_button.show()
+ self.client_auth_toggle_button.show()
def update(self):
"""
@@ -260,10 +342,15 @@ class ServerStatus(QtWidgets.QWidget):
)
else:
self.url_description.hide()
+ self.url_instructions.hide()
self.url.hide()
self.copy_url_button.hide()
- self.copy_client_auth_button.hide()
self.show_url_qr_code_button.hide()
+ self.private_key.hide()
+ self.client_auth_instructions.hide()
+ self.copy_client_auth_button.hide()
+ self.show_client_auth_qr_code_button.hide()
+ self.client_auth_toggle_button.hide()
self.mode_settings_widget.update_ui()
@@ -411,11 +498,32 @@ class ServerStatus(QtWidgets.QWidget):
"""
Show a QR code of the onion URL.
"""
- if self.settings.get("general", "public"):
- self.qr_code_dialog = QRCodeDialog(self.common, self.get_url())
+ self.qr_code_dialog = QRCodeDialog(
+ self.common, strings._("gui_qr_label_url_title"), self.get_url()
+ )
+
+ def show_client_auth_qr_code_button_clicked(self):
+ """
+ Show a QR code of the private key
+ """
+ self.qr_code_dialog = QRCodeDialog(
+ self.common,
+ strings._("gui_qr_label_auth_string_title"),
+ self.app.auth_string,
+ )
+
+ def client_auth_toggle_button_clicked(self):
+ """
+ ClientAuth reveal/hide toggle button clicked
+ """
+ if self.private_key_hidden:
+ self.private_key_hidden = False
+ self.client_auth_toggle_button.setText(strings._("gui_hide"))
else:
- # Make a QR Code for the ClientAuth too
- self.qr_code_dialog = QRCodeDialog(self.common, self.get_url(), self.app.auth_string)
+ self.private_key_hidden = True
+ self.client_auth_toggle_button.setText(strings._("gui_reveal"))
+
+ self.show_url()
def start_server(self):
"""
diff --git a/desktop/src/onionshare/widgets.py b/desktop/src/onionshare/widgets.py
index ec4d5ddc..b396c43f 100644
--- a/desktop/src/onionshare/widgets.py
+++ b/desktop/src/onionshare/widgets.py
@@ -130,47 +130,26 @@ class QRCodeDialog(QtWidgets.QDialog):
A dialog showing a QR code.
"""
- def __init__(self, common, url, auth_string=None):
+ def __init__(self, common, title, text):
super(QRCodeDialog, self).__init__()
self.common = common
self.common.log("QrCode", "__init__")
- self.qr_label_url = QtWidgets.QLabel(self)
- self.qr_label_url.setPixmap(qrcode.make(url, image_factory=Image).pixmap())
- self.qr_label_url.setScaledContents(True)
- self.qr_label_url.setFixedSize(350, 350)
- self.qr_label_url_title = QtWidgets.QLabel(self)
- self.qr_label_url_title.setText(strings._("gui_qr_label_url_title"))
- self.qr_label_url_title.setAlignment(QtCore.Qt.AlignCenter)
+ self.qr_label_title = QtWidgets.QLabel(self)
+ self.qr_label_title.setText(title)
+ self.qr_label_title.setAlignment(QtCore.Qt.AlignCenter)
+
+ self.qr_label = QtWidgets.QLabel(self)
+ self.qr_label.setPixmap(qrcode.make(text, image_factory=Image).pixmap())
+ self.qr_label.setScaledContents(True)
+ self.qr_label.setFixedSize(350, 350)
self.setWindowTitle(strings._("gui_qr_code_dialog_title"))
self.setWindowIcon(QtGui.QIcon(GuiCommon.get_resource_path("images/logo.png")))
- layout = QtWidgets.QHBoxLayout(self)
- url_layout = QtWidgets.QVBoxLayout(self)
- url_layout.addWidget(self.qr_label_url_title)
- url_layout.addWidget(self.qr_label_url)
-
- url_code_with_label = QtWidgets.QWidget()
- url_code_with_label.setLayout(url_layout)
- layout.addWidget(url_code_with_label)
-
- if auth_string:
- self.qr_label_auth_string = QtWidgets.QLabel(self)
- self.qr_label_auth_string.setPixmap(qrcode.make(auth_string, image_factory=Image).pixmap())
- self.qr_label_auth_string.setScaledContents(True)
- self.qr_label_auth_string.setFixedSize(350, 350)
- self.qr_label_auth_string_title = QtWidgets.QLabel(self)
- self.qr_label_auth_string_title.setText(strings._("gui_qr_label_auth_string_title"))
- self.qr_label_auth_string_title.setAlignment(QtCore.Qt.AlignCenter)
-
- auth_string_layout = QtWidgets.QVBoxLayout(self)
- auth_string_layout.addWidget(self.qr_label_auth_string_title)
- auth_string_layout.addWidget(self.qr_label_auth_string)
-
- auth_string_code_with_label = QtWidgets.QWidget()
- auth_string_code_with_label.setLayout(auth_string_layout)
- layout.addWidget(auth_string_code_with_label)
+ layout = QtWidgets.QVBoxLayout(self)
+ layout.addWidget(self.qr_label_title)
+ layout.addWidget(self.qr_label)
self.exec_()
diff --git a/desktop/tests/gui_base_test.py b/desktop/tests/gui_base_test.py
index ac2dfc54..83ad5fa3 100644
--- a/desktop/tests/gui_base_test.py
+++ b/desktop/tests/gui_base_test.py
@@ -270,10 +270,39 @@ class GuiBaseTest(unittest.TestCase):
tab.get_mode().server_status.file_selection.add_button.isVisible()
)
+ def url_shown(self, tab):
+ """Test that the URL is showing"""
+ self.assertTrue(tab.get_mode().server_status.url.isVisible())
+
def url_description_shown(self, tab):
"""Test that the URL label is showing"""
self.assertTrue(tab.get_mode().server_status.url_description.isVisible())
+ def url_instructions_shown(self, tab):
+ """Test that the URL instructions for sharing are showing"""
+ self.assertTrue(tab.get_mode().server_status.url_instructions.isVisible())
+
+ def private_key_shown(self, tab):
+ """Test that the Private Key is showing when not in public mode"""
+ if not tab.settings.get("general", "public"):
+ self.assertTrue(tab.get_mode().server_status.private_key.isVisible())
+ else:
+ self.assertFalse(tab.get_mode().server_status.private_key.isVisible())
+
+ def client_auth_instructions_shown(self, tab):
+ """
+ Test that the Private Key instructions for sharing
+ are showing when not in public mode
+ """
+ if not tab.settings.get("general", "public"):
+ self.assertTrue(
+ tab.get_mode().server_status.client_auth_instructions.isVisible()
+ )
+ else:
+ self.assertFalse(
+ tab.get_mode().server_status.client_auth_instructions.isVisible()
+ )
+
def have_copy_url_button(self, tab):
"""Test that the Copy URL button is shown and that the clipboard is correct"""
self.assertTrue(tab.get_mode().server_status.copy_url_button.isVisible())
@@ -282,7 +311,7 @@ class GuiBaseTest(unittest.TestCase):
clipboard = tab.common.gui.qtapp.clipboard()
self.assertEqual(clipboard.text(), f"http://127.0.0.1:{tab.app.port}")
- def have_show_qr_code_button(self, tab):
+ def have_show_url_qr_code_button(self, tab):
"""Test that the Show QR Code URL button is shown and that it loads a QR Code Dialog"""
self.assertTrue(
tab.get_mode().server_status.show_url_qr_code_button.isVisible()
@@ -296,6 +325,28 @@ class GuiBaseTest(unittest.TestCase):
QtCore.QTimer.singleShot(500, accept_dialog)
tab.get_mode().server_status.show_url_qr_code_button.click()
+ def have_show_client_auth_qr_code_button(self, tab):
+ """
+ Test that the Show QR Code Client Auth button is shown when
+ not in public mode and that it loads a QR Code Dialog.
+ """
+ if not tab.settings.get("general", "public"):
+ self.assertTrue(
+ tab.get_mode().server_status.show_client_auth_qr_code_button.isVisible()
+ )
+
+ def accept_dialog():
+ window = tab.common.gui.qtapp.activeWindow()
+ if window:
+ window.close()
+
+ QtCore.QTimer.singleShot(500, accept_dialog)
+ tab.get_mode().server_status.show_client_auth_qr_code_button.click()
+ else:
+ self.assertFalse(
+ tab.get_mode().server_status.show_client_auth_qr_code_button.isVisible()
+ )
+
def server_status_indicator_says_started(self, tab):
"""Test that the Server Status indicator shows we are started"""
if type(tab.get_mode()) == ReceiveMode:
@@ -344,10 +395,16 @@ class GuiBaseTest(unittest.TestCase):
self.assertFalse(tab.get_mode().server_status.copy_url_button.isVisible())
self.assertFalse(tab.get_mode().server_status.url.isVisible())
self.assertFalse(tab.get_mode().server_status.url_description.isVisible())
+ self.assertFalse(tab.get_mode().server_status.url_instructions.isVisible())
+ self.assertFalse(tab.get_mode().server_status.private_key.isVisible())
+ self.assertFalse(
+ tab.get_mode().server_status.client_auth_instructions.isVisible()
+ )
self.assertFalse(
tab.get_mode().server_status.copy_client_auth_button.isVisible()
)
+
def web_server_is_stopped(self, tab):
"""Test that the web server also stopped"""
QtTest.QTest.qWait(800, self.gui.qtapp)
diff --git a/desktop/tests/test_gui_chat.py b/desktop/tests/test_gui_chat.py
index 246a4494..786782f7 100644
--- a/desktop/tests/test_gui_chat.py
+++ b/desktop/tests/test_gui_chat.py
@@ -37,8 +37,13 @@ class TestChat(GuiBaseTest):
self.server_is_started(tab, startup_time=500)
self.web_server_is_running(tab)
self.url_description_shown(tab)
+ self.url_instructions_shown(tab)
+ self.url_shown(tab)
self.have_copy_url_button(tab)
- self.have_show_qr_code_button(tab)
+ self.have_show_url_qr_code_button(tab)
+ self.private_key_shown(tab)
+ self.client_auth_instructions_shown(tab)
+ self.have_show_client_auth_qr_code_button(tab)
self.server_status_indicator_says_started(tab)
def run_all_chat_mode_stopping_tests(self, tab):
diff --git a/desktop/tests/test_gui_receive.py b/desktop/tests/test_gui_receive.py
index af04a914..ca69c957 100644
--- a/desktop/tests/test_gui_receive.py
+++ b/desktop/tests/test_gui_receive.py
@@ -110,8 +110,13 @@ class TestReceive(GuiBaseTest):
self.server_is_started(tab)
self.web_server_is_running(tab)
self.url_description_shown(tab)
+ self.url_instructions_shown(tab)
+ self.url_shown(tab)
self.have_copy_url_button(tab)
- self.have_show_qr_code_button(tab)
+ self.have_show_url_qr_code_button(tab)
+ self.client_auth_instructions_shown(tab)
+ self.private_key_shown(tab)
+ self.have_show_client_auth_qr_code_button(tab)
self.server_status_indicator_says_started(tab)
def run_all_receive_mode_tests(self, tab):
diff --git a/desktop/tests/test_gui_share.py b/desktop/tests/test_gui_share.py
index b7a66a81..d3536569 100644
--- a/desktop/tests/test_gui_share.py
+++ b/desktop/tests/test_gui_share.py
@@ -182,8 +182,13 @@ class TestShare(GuiBaseTest):
self.server_is_started(tab, startup_time)
self.web_server_is_running(tab)
self.url_description_shown(tab)
+ self.url_instructions_shown(tab)
+ self.url_shown(tab)
self.have_copy_url_button(tab)
- self.have_show_qr_code_button(tab)
+ self.have_show_url_qr_code_button(tab)
+ self.private_key_shown(tab)
+ self.client_auth_instructions_shown(tab)
+ self.have_show_client_auth_qr_code_button(tab)
self.server_status_indicator_says_started(tab)
def run_all_share_mode_download_tests(self, tab):
diff --git a/desktop/tests/test_gui_website.py b/desktop/tests/test_gui_website.py
index d7a75ed6..e736874a 100644
--- a/desktop/tests/test_gui_website.py
+++ b/desktop/tests/test_gui_website.py
@@ -46,8 +46,13 @@ class TestWebsite(GuiBaseTest):
self.server_is_started(tab, startup_time)
self.web_server_is_running(tab)
self.url_description_shown(tab)
+ self.url_instructions_shown(tab)
+ self.url_shown(tab)
self.have_copy_url_button(tab)
- self.have_show_qr_code_button(tab)
+ self.have_show_url_qr_code_button(tab)
+ self.client_auth_instructions_shown(tab)
+ self.private_key_shown(tab)
+ self.have_show_client_auth_qr_code_button(tab)
self.server_status_indicator_says_started(tab)
def run_all_website_mode_download_tests(self, tab):