Merge pull request #20 from Bananaman/launch_rework

Improved game executable launcher, and added argument validation
This commit is contained in:
kramo
2023-03-24 22:42:09 +01:00
committed by GitHub
9 changed files with 38 additions and 27 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/subprojects/blueprint-compiler
/.flatpak
/.flatpak-builder
/.vscode

View File

@@ -95,7 +95,6 @@ def bottles_parser(parent_widget, action):
with open(os.path.join(bottles_dir, "library.yml"), "r") as open_file:
data = open_file.read()
open_file.close()
library = yaml.load(data, Loader=yaml.Loader)
@@ -112,9 +111,10 @@ def bottles_parser(parent_widget, action):
continue
values["name"] = game["name"]
values["executable"] = "xdg-open " + shlex.quote(
values["executable"] = [
"xdg-open",
f'bottles:run/{game["bottle"]["name"]}/{game["name"]}'
)
]
values["hidden"] = False
values["source"] = "bottles"
values["added"] = current_time

View File

@@ -19,6 +19,7 @@
import json
import os
import shlex
import time
from gi.repository import Adw, GdkPixbuf, Gio, GLib, GObject, Gtk
@@ -52,7 +53,7 @@ def create_details_window(parent_widget, game_id=None):
)
name = Gtk.Entry.new_with_buffer(Gtk.EntryBuffer.new(games[game_id].name, -1))
executable = Gtk.Entry.new_with_buffer(
Gtk.EntryBuffer.new((games[game_id].executable), -1)
Gtk.EntryBuffer.new(shlex.join(games[game_id].executable), -1)
)
apply_button = Gtk.Button.new_with_label(_("Apply"))
@@ -201,6 +202,21 @@ def create_details_window(parent_widget, game_id=None):
final_developer = developer.get_buffer().get_text()
final_executable = executable.get_buffer().get_text()
try:
# Attempt to parse using shell parsing rules (doesn't verify executable existence).
final_executable_split = shlex.split(
final_executable, comments=False, posix=True
)
except Exception as e:
create_dialog(
window,
_("Couldn't Add Game")
if game_id is None
else _("Couldn't Apply Preferences"),
f'{_("Executable")}: {e}.', # e = Shell parsing error message. Not translatable.
)
return
if game_id is None:
if final_name == "":
create_dialog(
@@ -252,7 +268,7 @@ def create_details_window(parent_widget, game_id=None):
values["name"] = final_name
values["developer"] = final_developer or None
values["executable"] = final_executable
values["executable"] = final_executable_split
path = os.path.join(
os.path.join(
@@ -267,7 +283,6 @@ def create_details_window(parent_widget, game_id=None):
if os.path.exists(path):
with open(path, "r") as open_file:
data = json.loads(open_file.read())
open_file.close()
data.update(values)
save_games({game_id: data})
else:

View File

@@ -41,6 +41,6 @@ def get_games(game_ids=None):
for game in game_files:
with open(os.path.join(games_dir, game), "r") as open_file:
data = json.loads(open_file.read())
open_file.close()
games[data["game_id"]] = data
games[data["game_id"]] = data
return games

View File

@@ -107,7 +107,6 @@ def heroic_parser(parent_widget, action):
os.path.join(heroic_dir, "lib-cache", "library.json"), "r"
) as open_file:
data = open_file.read()
open_file.close()
library = json.loads(data)
try:
@@ -129,9 +128,9 @@ def heroic_parser(parent_widget, action):
values["name"] = game["title"]
values["developer"] = game["developer"]
values["executable"] = (
f"start heroic://launch/{app_name}"
["start", f"heroic://launch/{app_name}"]
if os.name == "nt"
else f"xdg-open heroic://launch/{app_name}"
else ["xdg-open", f"heroic://launch/{app_name}"]
)
values["hidden"] = False
values["source"] = "heroic_epic"
@@ -160,7 +159,6 @@ def heroic_parser(parent_widget, action):
os.path.join(heroic_dir, "gog_store", "installed.json"), "r"
) as open_file:
data = open_file.read()
open_file.close()
installed = json.loads(data)
for item in installed["installed"]:
values = {}
@@ -179,7 +177,6 @@ def heroic_parser(parent_widget, action):
os.path.join(heroic_dir, "gog_store", "library.json"), "r"
) as open_file:
data = open_file.read()
open_file.close()
library = json.loads(data)
for game in library["games"]:
if game["app_name"] == app_name:
@@ -195,9 +192,9 @@ def heroic_parser(parent_widget, action):
break
values["executable"] = (
f"start heroic://launch/{app_name}"
["start", f"heroic://launch/{app_name}"]
if os.name == "nt"
else f"xdg-open heroic://launch/{app_name}"
else ["xdg-open", f"heroic://launch/{app_name}"]
)
values["hidden"] = False
values["source"] = "heroic_gog"
@@ -214,7 +211,6 @@ def heroic_parser(parent_widget, action):
os.path.join(heroic_dir, "sideload_apps", "library.json"), "r"
) as open_file:
data = open_file.read()
open_file.close()
library = json.loads(data)
for item in library["games"]:
values = {}
@@ -230,9 +226,9 @@ def heroic_parser(parent_widget, action):
values["name"] = item["title"]
values["executable"] = (
f"start heroic://launch/{app_name}"
["start", f"heroic://launch/{app_name}"]
if os.name == "nt"
else f"xdg-open heroic://launch/{app_name}"
else ["xdg-open", f"heroic://launch/{app_name}"]
)
values["hidden"] = False
values["source"] = "heroic_sideload"

View File

@@ -18,6 +18,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import shlex
import subprocess
import sys
@@ -25,13 +26,14 @@ from gi.repository import Gio
def run_command(executable):
# The host environment vars are automatically passed through by Popen.
subprocess.Popen(
[f"flatpak-spawn --host {executable}"]
["flatpak-spawn", "--host", *executable] # Flatpak
if os.getenv("FLATPAK_ID") == "hu.kramo.Cartridges"
else executable.split()
else executable # Windows
if os.name == "nt"
else [executable],
shell=True,
else executable, # Linux/Others
shell=False, # If true, the extra arguments would incorrectly be given to the shell instead.
start_new_session=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0,
)

View File

@@ -35,4 +35,3 @@ def save_games(games):
for game in games:
with open(os.path.join(games_dir, f"{game}.json"), "w") as open_file:
open_file.write(json.dumps(games[game], indent=4, sort_keys=True))
open_file.close()

View File

@@ -49,7 +49,6 @@ def get_game(task, datatypes, current_time, parent_widget, appmanifest, steam_di
with open(appmanifest, "r") as open_file:
data = open_file.read()
open_file.close()
for datatype in datatypes:
value = re.findall(f'"{datatype}"\t\t"(.*)"\n', data)
values[datatype] = value[0]
@@ -64,9 +63,9 @@ def get_game(task, datatypes, current_time, parent_widget, appmanifest, steam_di
return
values["executable"] = (
f'start steam://rungameid/{values["appid"]}'
["start", f'steam://rungameid/{values["appid"]}']
if os.name == "nt"
else f'xdg-open steam://rungameid/{values["appid"]}'
else ["xdg-open", f'steam://rungameid/{values["appid"]}']
)
values["hidden"] = False
values["source"] = "steam"

View File

@@ -36,7 +36,6 @@ def toggle_hidden(game):
with open(os.path.join(games_dir, f"{game}.json"), "r") as open_file:
data = json.loads(open_file.read())
open_file.close()
data["hidden"] = not data["hidden"]