Merge pull request #3306 from PrismLauncher/backport-1555-to-release-9.x

[Backport release-9.x] Correctly expand environment variables for pre/post launch and wrapper commands
This commit is contained in:
Alexandru Ionut Tripon 2025-01-17 09:01:21 +02:00 committed by GitHub
commit c787e65ed4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 60 additions and 29 deletions

View File

@ -254,20 +254,60 @@ void LaunchTask::emitFailed(QString reason)
Task::emitFailed(reason);
}
void LaunchTask::substituteVariables(QStringList& args) const
QString expandVariables(const QString& input, QProcessEnvironment dict)
{
auto env = m_instance->createEnvironment();
QString result = input;
for (auto key : env.keys()) {
args.replaceInStrings("$" + key, env.value(key));
enum { base, maybeBrace, variable, brace } state = base;
int startIdx = -1;
for (int i = 0; i < result.length();) {
QChar c = result.at(i++);
switch (state) {
case base:
if (c == '$')
state = maybeBrace;
break;
case maybeBrace:
if (c == '{') {
state = brace;
startIdx = i;
} else if (c.isLetterOrNumber() || c == '_') {
state = variable;
startIdx = i - 1;
} else {
state = base;
}
break;
case brace:
if (c == '}') {
const auto res = dict.value(result.mid(startIdx, i - 1 - startIdx), "");
if (!res.isEmpty()) {
result.replace(startIdx - 2, i - startIdx + 2, res);
i = startIdx - 2 + res.length();
}
state = base;
}
break;
case variable:
if (!c.isLetterOrNumber() && c != '_') {
const auto res = dict.value(result.mid(startIdx, i - startIdx - 1), "");
if (!res.isEmpty()) {
result.replace(startIdx - 1, i - startIdx, res);
i = startIdx - 1 + res.length();
}
state = base;
}
break;
}
}
if (state == variable) {
if (const auto res = dict.value(result.mid(startIdx), ""); !res.isEmpty())
result.replace(startIdx - 1, result.length() - startIdx + 1, res);
}
return result;
}
void LaunchTask::substituteVariables(QString& cmd) const
QString LaunchTask::substituteVariables(QString& cmd, bool isLaunch) const
{
auto env = m_instance->createEnvironment();
for (auto key : env.keys()) {
cmd.replace("$" + key, env.value(key));
}
return expandVariables(cmd, isLaunch ? m_instance->createLaunchEnvironment() : m_instance->createEnvironment());
}

View File

@ -87,8 +87,7 @@ class LaunchTask : public Task {
shared_qobject_ptr<LogModel> getLogModel();
public:
void substituteVariables(QStringList& args) const;
void substituteVariables(QString& cmd) const;
QString substituteVariables(QString& cmd, bool isLaunch = false) const;
QString censorPrivateInfo(QString in);
protected: /* methods */

View File

@ -47,19 +47,15 @@ PostLaunchCommand::PostLaunchCommand(LaunchTask* parent) : LaunchStep(parent)
void PostLaunchCommand::executeTask()
{
// FIXME: where to put this?
auto cmd = m_parent->substituteVariables(m_command);
emit logLine(tr("Running Post-Launch command: %1").arg(cmd), MessageLevel::Launcher);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
auto args = QProcess::splitCommand(m_command);
m_parent->substituteVariables(args);
auto args = QProcess::splitCommand(cmd);
emit logLine(tr("Running Post-Launch command: %1").arg(args.join(' ')), MessageLevel::Launcher);
const QString program = args.takeFirst();
m_process.start(program, args);
#else
m_parent->substituteVariables(m_command);
emit logLine(tr("Running Post-Launch command: %1").arg(m_command), MessageLevel::Launcher);
m_process.start(m_command);
m_process.start(cmd);
#endif
}

View File

@ -47,19 +47,14 @@ PreLaunchCommand::PreLaunchCommand(LaunchTask* parent) : LaunchStep(parent)
void PreLaunchCommand::executeTask()
{
// FIXME: where to put this?
auto cmd = m_parent->substituteVariables(m_command);
emit logLine(tr("Running Pre-Launch command: %1").arg(cmd), MessageLevel::Launcher);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
auto args = QProcess::splitCommand(m_command);
m_parent->substituteVariables(args);
emit logLine(tr("Running Pre-Launch command: %1").arg(args.join(' ')), MessageLevel::Launcher);
auto args = QProcess::splitCommand(cmd);
const QString program = args.takeFirst();
m_process.start(program, args);
#else
m_parent->substituteVariables(m_command);
emit logLine(tr("Running Pre-Launch command: %1").arg(m_command), MessageLevel::Launcher);
m_process.start(m_command);
m_process.start(cmd);
#endif
}

View File

@ -131,6 +131,7 @@ void LauncherPartLaunch::executeTask()
QString wrapperCommandStr = instance->getWrapperCommand().trimmed();
if (!wrapperCommandStr.isEmpty()) {
wrapperCommandStr = m_parent->substituteVariables(wrapperCommandStr);
auto wrapperArgs = Commandline::splitArgs(wrapperCommandStr);
auto wrapperCommand = wrapperArgs.takeFirst();
auto realWrapperCommand = QStandardPaths::findExecutable(wrapperCommand);