Skip to content

Commit fc7c696

Browse files
committed
Fixed #108, added user input sanitization for interruptions
1 parent aa647c4 commit fc7c696

File tree

5 files changed

+15
-9
lines changed

5 files changed

+15
-9
lines changed

res/CHANGELOG.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ Technical improvements:
3131

3232
Bug fixes:
3333

34+
- Selecting directory as log file (#108).
3435
- Window icon on Wayland (#110).
35-
- Line breaks in work items and backlogs.
36+
- Line breaks in work items and backlogs (#132).
3637

3738
- TODO: [Bugfix] Application icon in DEB / GNOME (#121)
3839
- TODO: [Bugfix] Unhandled IndexError - Changing audio devices while Flowkeeper is running (#120)
39-
- TODO: [Bugfix] Unhandled IsADirectoryError (#108)
4040
- TODO: [Bugfix] Entry point not found - OpenSSL preinstalled on Windows (#82)
4141
- TODO: [Technical] Windows binaries are now built using ???, which has better tolerance to Defender (#114)
4242
- TODO: [Technical] Windows binaries are checked via VirusTotal every night (#109)

src/fk/core/abstract_serializer.py

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
TRoot = TypeVar('TRoot')
2525

2626

27+
def sanitize_user_input(s: str) -> str:
28+
return s.replace('\n', ' ').replace('\r', '')
29+
30+
2731
class AbstractSerializer(ABC, Generic[T, TRoot]):
2832
_settings: AbstractSettings
2933
_cryptograph: AbstractCryptograph

src/fk/desktop/application.py

+4
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ def _initialize_logger(self):
212212

213213
# 2. Check that the entire logger file path exists
214214
filename = self._settings.get('Logger.filename')
215+
logfile = Path(filename)
216+
if logfile.is_dir(): # Fixing #108 - a rare case when the user selects directory as log filename
217+
logfile /= 'flowkeeper.log'
218+
filename = logfile.absolute()
215219
prepare_file_for_writing(filename)
216220

217221
# 3. Add FILE handler for whatever the user configured

src/fk/qt/abstract_drop_model.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,13 @@
2525

2626
from fk.core.abstract_data_container import AbstractDataContainer
2727
from fk.core.abstract_data_item import AbstractDataItem
28+
from fk.core.abstract_serializer import sanitize_user_input
2829
from fk.core.abstract_strategy import AbstractStrategy
2930
from fk.core.event_source_holder import EventSourceHolder
3031

3132
logger = logging.getLogger(__name__)
3233

3334

34-
def sanitize(s: str) -> str:
35-
return s.replace('\n', ' ').replace('\r', '')
36-
37-
3835
class DropPlaceholderItem(QStandardItem):
3936
def __init__(self, height: int):
4037
super().__init__()
@@ -96,7 +93,7 @@ def handle_rename(self, item: QStandardItem, strategy_class: type[AbstractStrate
9693
if item.data(501) == 'title':
9794
entity: AbstractDataContainer = item.data(500)
9895
old_name = entity.get_name()
99-
new_name = sanitize(item.text())
96+
new_name = sanitize_user_input(item.text())
10097
if old_name != new_name:
10198
try:
10299
self._source_holder.get_source().execute(strategy_class, [entity.get_uid(), new_name])

src/fk/qt/focus_widget.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
QSpacerItem, QInputDialog, QLineEdit
2222

2323
from fk.core.abstract_event_source import AbstractEventSource, start_workitem
24+
from fk.core.abstract_serializer import sanitize_user_input
2425
from fk.core.abstract_settings import AbstractSettings
2526
from fk.core.abstract_timer_display import AbstractTimerDisplay
2627
from fk.core.event_source_holder import EventSourceHolder
@@ -320,7 +321,7 @@ def _void_pomodoro(self) -> None:
320321
dlg.setLabelText('Are you sure you want to void current pomodoro?')
321322
dlg.findChild(QLineEdit).setPlaceholderText('Reason (optional)')
322323
if dlg.exec_():
323-
reason = f': {dlg.textValue()}' if dlg.textValue() else ''
324+
reason = f': {sanitize_user_input(dlg.textValue())}' if dlg.textValue() else ''
324325
self._source_holder.get_source().execute(AddInterruptionStrategy,
325326
[workitem.get_uid(), f'Pomodoro voided{reason}'])
326327
self._source_holder.get_source().execute(StopTimerStrategy,
@@ -338,7 +339,7 @@ def _interruption(self) -> None:
338339
dlg.findChild(QLineEdit).setPlaceholderText('What happened (optional)')
339340
if dlg.exec_():
340341
self._source_holder.get_source().execute(AddInterruptionStrategy,
341-
[workitem.get_uid(), dlg.textValue()])
342+
[workitem.get_uid(), sanitize_user_input(dlg.textValue())])
342343

343344
def _finish_tracking(self) -> None:
344345
# We don't check if there's a running workitem, as the action is only enabled while the timer is ticking

0 commit comments

Comments
 (0)