Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions src/tagstudio/core/library/refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,16 @@ def __get_dir_list(self, library_dir: Path, ignore_patterns: list[str]) -> list[
pattern_file.write("\n".join(ignore_patterns))

result = silent_run(
" ".join(
[
"rg",
"--files",
"--follow",
"--hidden",
"--ignore-file",
f'"{str(compiled_ignore_path)}"',
]
),
[
"rg",
"--files",
"--follow",
"--hidden",
"--ignore-file",
str(compiled_ignore_path),
],
cwd=library_dir,
capture_output=True,
shell=True,
encoding="UTF-8",
)
compiled_ignore_path.unlink()
Expand Down
26 changes: 6 additions & 20 deletions src/tagstudio/qt/utils/file_opener.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Licensed under the GPL-3.0 License.
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio

import os
import shutil
import subprocess
import sys
Expand Down Expand Up @@ -40,39 +41,24 @@ def open_file(path: str | Path, file_manager: bool = False, windows_start_comman
if sys.platform == "win32":
normpath = str(Path(path).resolve())
if file_manager:
command_name = "explorer"
command_arg = f'/select,"{normpath}"'

# For some reason, if the args are passed in a list, this will error when the
# path has spaces, even while surrounded in double quotes.
# /select, takes the path as a single comma-joined argument.
silent_popen(
command_name + command_arg,
shell=True,
["explorer", f"/select,{normpath}"],
close_fds=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
| subprocess.CREATE_BREAKAWAY_FROM_JOB,
)
else:
if windows_start_command:
command_name = "start"
# First parameter is for title, NOT filepath
command_args = ["", normpath]
# First "" is the start-command title slot, not the filepath.
subprocess.Popen(
[command_name] + command_args,
shell=True,
Comment on lines -61 to -62
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not on windows so I can't check, but it seems to me like removing shell = True and then calling the shell manually instead would still cause shell meta chars to be parsed (as it would with bash -c "<cmd>". (Although the syntax of /c is different from bash so maybe not)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Craaaaaap. You're right. I think it'll still expand stuff like %VAR%, too after /c.

If we have to keep the edge case and still use cmd, we could wrap the whole path in double quotes and parse the guts of the string for internal double quotes and percents, then toss them? Or just reject the string. It wouldn't be perfect, but it's better than sending raw stuff to cmd.

Another option is PowerShell, but that could run into ExecutionPolicy issues, depending on how the host is configured. I know I lock down ExecutionPolicy for my users via group policy to make sure they don't get up to shenanigans.

Something like this with -LiteralPath could work since it won't expand into anything weird:

  def _open_with_powershell(normpath: str) -> None:
      escaped = normpath.replace("'", "''")
      ps_script = f"Start-Process -FilePath '{escaped}'"
      # -EncodedCommand wants base64 of UTF-16LE.
      encoded = base64.b64encode(ps_script.encode("utf-16-le")).decode("ascii")
      silent_popen(
          ["powershell", "-NoProfile", "-NonInteractive", "-EncodedCommand", encoded],
          close_fds=True,
          creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
          | subprocess.CREATE_BREAKAWAY_FROM_JOB,
      )

  if windows_start_command:
      _open_with_powershell(normpath)
  else:
      os.startfile(normpath)

Otherwise, if we don't need the edge case, os.startfile path would still be the way to do it.

Thoughts?

["cmd", "/c", "start", "", normpath],
close_fds=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
| subprocess.CREATE_BREAKAWAY_FROM_JOB,
)
else:
command = f'"{normpath}"'
silent_popen(
command,
shell=True,
close_fds=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
| subprocess.CREATE_BREAKAWAY_FROM_JOB,
)
os.startfile(normpath)
else:
if sys.platform == "darwin":
command_name = "open"
Expand Down