From 2e916be88b4d92350585c6952a798aaaef491714 Mon Sep 17 00:00:00 2001 From: Paul Nameless Date: Sat, 20 Jun 2020 21:54:50 +0800 Subject: [PATCH 1/2] Shell-escape file path passed to commands --- tg/config.py | 10 +++++----- tg/controllers.py | 13 +++++++++---- tg/utils.py | 8 +++++--- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/tg/config.py b/tg/config.py index 541eb08..9b4b176 100644 --- a/tg/config.py +++ b/tg/config.py @@ -31,17 +31,17 @@ TDLIB_VERBOSITY = 0 MAX_DOWNLOAD_SIZE = "10MB" # TODO: check platform -NOTIFY_CMD = "/usr/local/bin/terminal-notifier -title '{title}' -subtitle '{subtitle}' -message '{msg}' -appIcon '{icon_path}'" +NOTIFY_CMD = "/usr/local/bin/terminal-notifier -title {title} -subtitle {subtitle} -message {msg} -appIcon {icon_path}" HELP_CMD = "less" if _os_name == _linux: VOICE_RECORD_CMD = ( - "ffmpeg -f alsa -i default -c:a libopus -b:a 32k '{file_path}'" + "ffmpeg -f alsa -i default -c:a libopus -b:a 32k {file_path}" ) else: VOICE_RECORD_CMD = ( - "ffmpeg -f avfoundation -i ':0' -c:a libopus -b:a 32k '{file_path}'" + "ffmpeg -f avfoundation -i ':0' -c:a libopus -b:a 32k {file_path}" ) # TODO: use mailcap instead of editor @@ -49,9 +49,9 @@ LONG_MSG_CMD = "vim + -c 'startinsert' {file_path}" EDITOR = os.environ.get("EDITOR", "vi") if _os_name == _linux: - DEFAULT_OPEN = "xdg-open '{file_path}'" + DEFAULT_OPEN = "xdg-open {file_path}" else: - DEFAULT_OPEN = "open '{file_path}'" + DEFAULT_OPEN = "open {file_path}" if _os_name == _linux: COPY_CMD = "xclip -selection c" diff --git a/tg/controllers.py b/tg/controllers.py index 4a27b12..43b52ea 100644 --- a/tg/controllers.py +++ b/tg/controllers.py @@ -1,6 +1,7 @@ import curses import logging import os +import shlex import threading from datetime import datetime from functools import partial, wraps @@ -91,7 +92,7 @@ class Controller: return if len(urls) == 1: with suspend(self.view) as s: - s.call(config.DEFAULT_OPEN.format(file_path=url)) + s.call(config.DEFAULT_OPEN.format(file_path=shlex.quote(url))) return with suspend(self.view) as s: s.run_with_input(config.URL_VIEW, "\n".join(urls)) @@ -224,7 +225,7 @@ class Controller: ) as s: f.write(insert_replied_msg(msg)) f.seek(0) - s.call(config.LONG_MSG_CMD.format(file_path=f.name)) + s.call(config.LONG_MSG_CMD.format(file_path=shlex.quote(f.name))) with open(f.name) as f: if msg := strip_replied_msg(f.read().strip()): self.tg.reply_message(chat_id, reply_to_msg, msg) @@ -251,7 +252,7 @@ class Controller: with NamedTemporaryFile("r+", suffix=".txt") as f, suspend( self.view ) as s: - s.call(config.LONG_MSG_CMD.format(file_path=f.name)) + s.call(config.LONG_MSG_CMD.format(file_path=shlex.quote(f.name))) with open(f.name) as f: if msg := f.read().strip(): self.model.send_message(text=msg) @@ -301,7 +302,11 @@ class Controller: def record_voice(self): file_path = f"/tmp/voice-{datetime.now()}.oga" with suspend(self.view) as s: - s.call(config.VOICE_RECORD_CMD.format(file_path=file_path)) + s.call( + config.VOICE_RECORD_CMD.format( + file_path=shlex.quote(file_path) + ) + ) resp = self.view.status.get_input( f"Do you want to send recording: {file_path}? [Y/n]" ) diff --git a/tg/utils.py b/tg/utils.py index 128cc94..47a9a7d 100644 --- a/tg/utils.py +++ b/tg/utils.py @@ -74,7 +74,7 @@ def get_file_handler(file_path, default=None): caps = mailcap.getcaps() handler, view = mailcap.findmatch(caps, mtype, filename=file_path) if not handler: - return config.DEFAULT_OPEN.format(file_path=file_path) + return config.DEFAULT_OPEN.format(file_path=shlex.quote(file_path)) return handler @@ -148,9 +148,11 @@ def notify( if not cmd: return notify_cmd = cmd.format( - icon_path=config.ICON_PATH, title=title, subtitle=subtitle, msg=msg + icon_path=shlex.quote(config.ICON_PATH), + title=shlex.quote(title), + subtitle=shlex.quote(subtitle), + msg=shlex.quote(msg), ) - log.info("notify-cmd: %s", notify_cmd) os.system(notify_cmd) From 28760e0fa0a6d2037acf0176f320cbfa98088233 Mon Sep 17 00:00:00 2001 From: Paul Nameless Date: Sat, 20 Jun 2020 22:17:05 +0800 Subject: [PATCH 2/2] Update config info in README --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 35f56ef..af5f5fb 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ docker run -it --rm tg - `terminal-notifier` or other program for notifications (see configuration) - `ffmpeg` to record voice msgs and upload videos correctly -- [tdlib](https://tdlib.github.io/td/build.html?language=Python) - in case of incompatibility with built in package +- [tdlib](https://tdlib.github.io/td/build.html?language=Python) - in case of incompatibility with built in package. For example, macOS: ```sh brew install tdlib @@ -99,16 +99,16 @@ LOG_PATH = "~/.local/share/tg/" # use your own, for example: TDLIB_PATH = "/usr/local/Cellar/tdlib/1.6.0/lib/libtdjson.dylib" -# you can use any other notification cmd, it is simple python file which +# you can use any other notification cmd, it is simple python string which # can format title, msg, subtitle and icon_path paramters # In these exapmle, kitty terminal is used and when notification is pressed # it will focus on the tab of running tg -NOTIFY_CMD = '/usr/local/bin/terminal-notifier -title "{title}" -subtitle "{subtitle}" -message "{msg}" -appIcon "{icon_path}" -sound default -execute \'/Applications/kitty.app/Contents/MacOS/kitty @ --to unix:/tmp/kitty focus-tab --no-response -m title:tg\'' +NOTIFY_CMD = "/usr/local/bin/terminal-notifier -title {title} -subtitle {subtitle} -message {msg} -appIcon {icon_path} -sound default -execute '/Applications/kitty.app/Contents/MacOS/kitty @ --to unix:/tmp/kitty focus-tab --no-response -m title:tg'" # You can use your own voice recording cmd but it's better to use default one. # The voice note must be encoded with the Opus codec, and stored inside an OGG # container. Voice notes can have only a single audio channel. -VOICE_RECORD_CMD = "ffmpeg -f avfoundation -i ':0' -c:a libopus -b:a 32k '{file_path}'" +VOICE_RECORD_CMD = "ffmpeg -f avfoundation -i ':0' -c:a libopus -b:a 32k {file_path}" # You can customize chat and msg flags however you want. # By default words will be used for readability, but you can make