Skip to content

Commit

Permalink
feat: escape user input in chat and boards to prevent markup issues
Browse files Browse the repository at this point in the history
  • Loading branch information
kc1awv committed Jan 19, 2025
1 parent 7b53d98 commit 7fd77a1
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 16 deletions.
Binary file added req.txt
Binary file not shown.
15 changes: 8 additions & 7 deletions server/boards_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import threading

from datetime import datetime, timezone
from rich.markup import escape

import RNS

Expand Down Expand Up @@ -309,7 +310,7 @@ def handle_list_messages(self, packet, remainder, user_hash, page=None, page_siz
for message in posts:
timestamp_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message["timestamp"]))
lines.append(
f"[{message['id']}] {timestamp_str} | {message['author']} | {message['topic']} "
f"[{message['id']}] {timestamp_str} | {escape(message['author'])} | {escape(message['topic'])} "
f"({message['reply_count']} replies)"
)
lines.append("\nCommands: 'r <id>' to read a message, < (prev) || > (next) for navigation.")
Expand All @@ -336,7 +337,7 @@ def handle_list_unread_messages(self, packet, user_hash):
lines = [f"Unread messages in board '{board_name}':"]
for m in unread_messages:
t_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(m["timestamp"]))
lines.append(f"[{m['id']}] {t_str} | {m['author']} | {m['topic']}")
lines.append(f"[{m['id']}] {t_str} | {escape(m['author'])} | {escape(m['topic'])}")
reply = "\n".join(lines)
self.reply_handler.send_resource_reply(packet.link, reply)

Expand Down Expand Up @@ -393,17 +394,17 @@ def handle_read_message(self, packet, message_id, user_hash):
reply = (
f"\n[bold]----- Message {message_id} -----[/]\n"
f"Timestamp: {t_str}\n"
f"Author: {message['author']}\n"
f"Topic: {message['topic']}\n"
f"Author: {escape(message['author'])}\n"
f"Topic: {escape(message['topic'])}\n"
"\n"
f"{message['content']}\n"
f"{escape(message['content'])}\n"
)
replies = self.list_replies(message_id)
if replies:
reply += "\nReplies:\n"
for r in replies:
r_t_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(r["timestamp"]))
reply += f" [{r['id']}] {r_t_str} | {r['author']}: {r['content']}\n"
reply += f" [{r['id']}] {r_t_str} | {escape(r['author'])}: {escape(r['content'])}\n"
reply += "\nTo reply, use: reply <message_id> | <content>"
self.mark_message_as_read(user_hash, message_id)
else:
Expand Down Expand Up @@ -467,7 +468,7 @@ def handle_post_message(self, packet, remainder, user_hash):
return
try:
self.post_message(board_name, author, topic, content)
reply = f"Posted to board '{board_name}': [{topic}] {content}"
reply = f"Posted to board '{board_name}': [{escape(topic)}] {escape(content)}"
self.reply_handler.send_link_reply(packet.link, reply)
self.notify_watchers(board_name, topic, content, author)
except Exception as e:
Expand Down
11 changes: 7 additions & 4 deletions server/chat/chat_manager.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from rich.markup import escape

import RNS

class ChatRoom:
Expand Down Expand Up @@ -29,7 +31,7 @@ def broadcast(self, message, sender=None):
"""
for user_hash in self.clients:
if user_hash != sender:
self.chat_manager.broadcast_to_user(user_hash, f"[{self.name}] {message}")
self.chat_manager.broadcast_to_user(user_hash, f"[{escape(self.name)}] {escape(message)}")
RNS.log(f"[ChatRoom] Broadcast to {user_hash}: {message}", RNS.LOG_DEBUG)

class ChatManager:
Expand Down Expand Up @@ -190,9 +192,9 @@ def handle_chat_message(self, packet, message, user_hash):
room = self.rooms.get(current_room_name)
if room:
user_display_name = self.users_mgr.get_user_display(user_hash)
room.broadcast(f"{user_display_name}: {message.strip()}", sender=user_hash)
room.broadcast(f"{escape(user_display_name)}: {escape(message.strip())}", sender=user_hash)
RNS.log(f"[ChatManager] Broadcast to {current_room_name}: {message.strip()}", RNS.LOG_DEBUG)
self.reply_handler.send_link_reply(packet.link, f"[{current_room_name}] (You): {message.strip()}")
self.reply_handler.send_link_reply(packet.link, f"[{current_room_name}] (You): {escape(message.strip())}")
else:
self.reply_handler.send_link_reply(packet.link, "ERROR: Chat room not found.")
else:
Expand Down Expand Up @@ -230,8 +232,9 @@ def leave_room(self, user_hash):
user_display_name = self.users_mgr.get_user_display(user_hash)
if room:
is_empty = room.remove_client(user_hash)
room.broadcast(f"{user_display_name} has left the room.")
room.broadcast(f"{escape(user_display_name)} has left the room.")
if is_empty:
del self.rooms[current_room_name]
RNS.log(f"[ChatManager] Removed empty room: {current_room_name}", RNS.LOG_DEBUG)
self.users_mgr.set_user_room(user_hash, None)
self.reply_handler.send_room_update(self.user_links[user_hash], None)
11 changes: 6 additions & 5 deletions server/main_menu.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
from rich.markup import escape

import RNS

Expand Down Expand Up @@ -74,7 +75,7 @@ def handle_hello(self, packet, user_hash):
"""
user = self.users_mgr.get_user(user_hash)
user_display_name = user.get("name", user_hash)
reply = f"Hello, {user_display_name}."
reply = f"Hello, {escape(user_display_name)}."
if user.get("is_admin", False):
reply += "\nYou have ADMIN rights."
destination_address = user.get("destination_address")
Expand All @@ -94,11 +95,11 @@ def handle_name(self, packet, remainder, user_hash):
return

if self.users_mgr.is_name_taken(proposed_name, exclude_hash_hex=user_hash):
self.reply_handler.send_link_reply(packet.link, f"ERROR: The name '{proposed_name}' is already taken.")
self.reply_handler.send_link_reply(packet.link, f"ERROR: The name '{escape(proposed_name)}' is already taken.")
return

self.users_mgr.update_user(user_hash, name=proposed_name)
self.reply_handler.send_link_reply(packet.link, f"Your display name is now set to '{proposed_name}'.")
self.reply_handler.send_link_reply(packet.link, f"Your display name is now set to '{escape(proposed_name)}'.")

def handle_set_destination_address(self, packet, remainder, user_hash):
"""
Expand Down Expand Up @@ -201,7 +202,7 @@ def handle_list_users(self, packet, user_hash):
for user in user_list:
name = user["name"] if user["name"] else "N/A"
admin_status = " (Admin)" if user["is_admin"] else ""
reply += f"- {user['hash_hex']} | {name}{admin_status}\n"
reply += f"- {user['hash_hex']} | {escape(name)} {admin_status}\n"
self.reply_handler.send_resource_reply(packet.link, reply)

def handle_admin(self, packet, remainder, user_hash):
Expand All @@ -225,4 +226,4 @@ def handle_admin(self, packet, remainder, user_hash):

self.users_mgr.update_user(target_hash, is_admin=True)
target_display_name = self.users_mgr.get_user_display(target_hash)
self.reply_handler.send_link_reply(packet.link, f"User {target_display_name} has been granted admin rights.")
self.reply_handler.send_link_reply(packet.link, f"User {escape(target_display_name)} has been granted admin rights.")

0 comments on commit 7fd77a1

Please sign in to comment.