summaryrefslogtreecommitdiff
path: root/onionshare
diff options
context:
space:
mode:
authorSaptak S <saptak013@gmail.com>2020-03-08 14:51:43 +0530
committerSaptak S <saptak013@gmail.com>2020-03-08 14:51:43 +0530
commit2c938fd777d24687e38ff53a6d2e8c317cecef82 (patch)
tree83ce74538b2a97882c6dacc8d4a798941a27a680 /onionshare
parenta217e54d28dd29ba1efc5314094f2b354320d69d (diff)
downloadonionshare-2c938fd777d24687e38ff53a6d2e8c317cecef82.tar.gz
onionshare-2c938fd777d24687e38ff53a6d2e8c317cecef82.zip
Create web UI and socket code for the chat interface
Diffstat (limited to 'onionshare')
-rw-r--r--onionshare/__init__.py6
-rw-r--r--onionshare/common.py10
-rw-r--r--onionshare/mode_settings.py1
-rw-r--r--onionshare/web/chat_mode.py75
-rw-r--r--onionshare/web/web.py14
5 files changed, 105 insertions, 1 deletions
diff --git a/onionshare/__init__.py b/onionshare/__init__.py
index 8d2077c2..fa58d859 100644
--- a/onionshare/__init__.py
+++ b/onionshare/__init__.py
@@ -63,6 +63,9 @@ def main(cwd=None):
parser.add_argument(
"--website", action="store_true", dest="website", help="Publish website"
)
+ parser.add_argument(
+ "--chat", action="store_true", dest="chat", help="Start chat server"
+ )
# Tor connection-related args
parser.add_argument(
"--local-only",
@@ -172,6 +175,7 @@ def main(cwd=None):
receive = bool(args.receive)
website = bool(args.website)
+ chat = bool(args.chat)
local_only = bool(args.local_only)
connect_timeout = int(args.connect_timeout)
config_filename = args.config
@@ -190,6 +194,8 @@ def main(cwd=None):
mode = "receive"
elif website:
mode = "website"
+ elif chat:
+ mode = "chat"
else:
mode = "share"
diff --git a/onionshare/common.py b/onionshare/common.py
index 7048c174..a4e2d8b6 100644
--- a/onionshare/common.py
+++ b/onionshare/common.py
@@ -215,6 +215,16 @@ class Common:
r = random.SystemRandom()
return "-".join(r.choice(wordlist) for _ in range(word_count))
+ def build_username(self, word_count=2):
+ """
+ Returns a random string made of words from the wordlist, such as "deter-trig".
+ """
+ with open(self.get_resource_path("wordlist.txt")) as f:
+ wordlist = f.read().split()
+
+ r = random.SystemRandom()
+ return "-".join(r.choice(wordlist) for _ in range(word_count))
+
@staticmethod
def random_string(num_bytes, output_len=None):
"""
diff --git a/onionshare/mode_settings.py b/onionshare/mode_settings.py
index 9201721e..8216c1d8 100644
--- a/onionshare/mode_settings.py
+++ b/onionshare/mode_settings.py
@@ -49,6 +49,7 @@ class ModeSettings:
"share": {"autostop_sharing": True, "filenames": []},
"receive": {"data_dir": self.build_default_receive_data_dir()},
"website": {"disable_csp": False, "filenames": []},
+ "chat": {"room": "default"},
}
self._settings = {}
diff --git a/onionshare/web/chat_mode.py b/onionshare/web/chat_mode.py
new file mode 100644
index 00000000..c81bd636
--- /dev/null
+++ b/onionshare/web/chat_mode.py
@@ -0,0 +1,75 @@
+import os
+import tempfile
+import json
+from datetime import datetime
+from flask import Request, request, render_template, make_response, flash, redirect, session
+from werkzeug.utils import secure_filename
+from flask_socketio import emit, join_room, leave_room
+
+from .. import strings
+
+
+class ChatModeWeb:
+ """
+ All of the web logic for chat mode
+ """
+
+ def __init__(self, common, web):
+ self.common = common
+ self.common.log("ChatModeWeb", "__init__")
+
+ self.web = web
+
+ self.can_upload = True
+ self.uploads_in_progress = []
+
+ # This tracks the history id
+ self.cur_history_id = 0
+
+ self.define_routes()
+
+ def define_routes(self):
+ """
+ The web app routes for chatting
+ """
+
+ @self.web.app.route("/")
+ def index():
+ history_id = self.cur_history_id
+ self.cur_history_id += 1
+ self.web.add_request(
+ self.web.REQUEST_INDIVIDUAL_FILE_STARTED,
+ request.path,
+ {"id": history_id, "status_code": 200},
+ )
+
+ self.web.add_request(self.web.REQUEST_LOAD, request.path)
+ r = make_response(
+ render_template(
+ "chat.html", static_url_path=self.web.static_url_path
+ )
+ )
+ return self.web.add_security_headers(r)
+
+ @self.web.socketio.on("joined", namespace="/chat")
+ def joined(message):
+ """Sent by clients when they enter a room.
+ A status message is broadcast to all people in the room."""
+ session["name"] = self.common.build_username()
+ session["room"] = self.web.settings.default_settings["chat"]["room"]
+ join_room(session.get("room"))
+ emit(
+ "status",
+ {"msg": session.get("name") + " has entered the room."},
+ room=session.get("room")
+ )
+
+ @self.web.socketio.on("text", namespace="/chat")
+ def text(message):
+ """Sent by a client when the user entered a new message.
+ The message is sent to all people in the room."""
+ emit(
+ "message",
+ {"msg": session.get("name") + ": " + message["msg"]},
+ room=session.get("room")
+ )
diff --git a/onionshare/web/web.py b/onionshare/web/web.py
index 8582e694..3a22c789 100644
--- a/onionshare/web/web.py
+++ b/onionshare/web/web.py
@@ -20,12 +20,14 @@ from flask import (
__version__ as flask_version,
)
from flask_httpauth import HTTPBasicAuth
+from flask_socketio import SocketIO
from .. import strings
from .share_mode import ShareModeWeb
from .receive_mode import ReceiveModeWeb, ReceiveModeWSGIMiddleware, ReceiveModeRequest
from .website_mode import WebsiteModeWeb
+from .chat_mode import ChatModeWeb
# Stub out flask's show_server_banner function, to avoiding showing warnings that
# are not applicable to OnionShare
@@ -134,12 +136,17 @@ class Web:
self.share_mode = None
self.receive_mode = None
self.website_mode = None
+ self.chat_mode = None
if self.mode == "share":
self.share_mode = ShareModeWeb(self.common, self)
elif self.mode == "receive":
self.receive_mode = ReceiveModeWeb(self.common, self)
elif self.mode == "website":
self.website_mode = WebsiteModeWeb(self.common, self)
+ elif self.mode == "chat":
+ self.socketio = SocketIO()
+ self.socketio.init_app(self.app)
+ self.chat_mode = ChatModeWeb(self.common, self)
def get_mode(self):
if self.mode == "share":
@@ -148,6 +155,8 @@ class Web:
return self.receive_mode
elif self.mode == "website":
return self.website_mode
+ elif self.mode == "chat":
+ return self.chat_mode
else:
return None
@@ -366,7 +375,10 @@ class Web:
host = "127.0.0.1"
self.running = True
- self.app.run(host=host, port=port, threaded=True)
+ if self.mode == "chat":
+ self.socketio.run(self.app, host=host, port=port)
+ else:
+ self.app.run(host=host, port=port, threaded=True)
def stop(self, port):
"""