feat: add env option and refactor command generate method
Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
		@ -80,7 +80,14 @@
 | 
			
		||||
                       Extra options can be passed in `options` argument:
 | 
			
		||||
                       1. `uid` (type u):
 | 
			
		||||
                          The user id as who is that application will be run.
 | 
			
		||||
                          This option might request a polikit authentication."
 | 
			
		||||
                          This option might request a polikit authentication.
 | 
			
		||||
                       2. `env` (type s):
 | 
			
		||||
                          passing some specific environment variables to Launch
 | 
			
		||||
                          this application, eg. 'LANG=en_US;PATH=xxx:yyy;'
 | 
			
		||||
 | 
			
		||||
                        NOTE:
 | 
			
		||||
                        when application try to be launched by other user identity,
 | 
			
		||||
                        all environment variables will be ignored.
 | 
			
		||||
            />
 | 
			
		||||
        </method>
 | 
			
		||||
    </interface>
 | 
			
		||||
 | 
			
		||||
@ -42,4 +42,8 @@ constexpr auto ApplicationManagerInterface = "org.desktopspec.ApplicationManager
 | 
			
		||||
constexpr auto InstanceInterface = "org.desktopspec.ApplicationManager1.Instance";
 | 
			
		||||
constexpr auto ApplicationInterface = "org.desktopspec.ApplicationManager1.Application";
 | 
			
		||||
 | 
			
		||||
constexpr auto systemdOption = u8"systemd";
 | 
			
		||||
constexpr auto splitOption = u8"split";
 | 
			
		||||
constexpr auto AppExecOption = u8"appExec";
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
#include "APPobjectmanager1adaptor.h"
 | 
			
		||||
#include "applicationmanager1service.h"
 | 
			
		||||
#include "dbus/instanceadaptor.h"
 | 
			
		||||
#include "pwd.h"
 | 
			
		||||
#include "launchoptions.h"
 | 
			
		||||
#include <QUuid>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QList>
 | 
			
		||||
@ -125,27 +125,13 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto [bin, cmds, res] = unescapeExec(execStr, fields);
 | 
			
		||||
    auto cmds = generateCommand(options);
 | 
			
		||||
 | 
			
		||||
    uid_t uid;
 | 
			
		||||
    auto it = options.find("uid");
 | 
			
		||||
    if (it != options.cend()) {
 | 
			
		||||
        uid = it->toUInt(&ok);
 | 
			
		||||
        if (!ok) {
 | 
			
		||||
            qWarning() << "convert uid string to uint failed: " << *it;
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
    auto [bin, execCmds, res] = unescapeExec(execStr, fields);
 | 
			
		||||
 | 
			
		||||
        if (uid != getCurrentUID()) {
 | 
			
		||||
            cmds.prepend(userNameLookup(uid));
 | 
			
		||||
            cmds.prepend("--user");
 | 
			
		||||
            cmds.prepend("pkexec");
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        uid = getCurrentUID();
 | 
			
		||||
    }
 | 
			
		||||
    cmds.append(std::move(execCmds));
 | 
			
		||||
 | 
			
		||||
    cmds.prepend("--");
 | 
			
		||||
    qDebug() << "run application with:" << cmds;
 | 
			
		||||
 | 
			
		||||
    auto &jobManager = static_cast<ApplicationManager1Service *>(parent())->jobManager();
 | 
			
		||||
 | 
			
		||||
@ -348,12 +334,6 @@ void ApplicationService::resetEntry(DesktopEntry *newEntry) noexcept
 | 
			
		||||
    m_entry.reset(newEntry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString ApplicationService::userNameLookup(uid_t uid)
 | 
			
		||||
{
 | 
			
		||||
    auto *pws = getpwuid(uid);
 | 
			
		||||
    return pws->pw_name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LaunchTask ApplicationService::unescapeExec(const QString &str, const QStringList &fields)
 | 
			
		||||
{
 | 
			
		||||
    LaunchTask task;
 | 
			
		||||
 | 
			
		||||
@ -97,7 +97,6 @@ private:
 | 
			
		||||
    DesktopFile m_desktopSource;
 | 
			
		||||
    QSharedPointer<DesktopEntry> m_entry{nullptr};
 | 
			
		||||
    QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
 | 
			
		||||
    static QString userNameLookup(uid_t uid);
 | 
			
		||||
    [[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
 | 
			
		||||
    [[nodiscard]] QVariant findEntryValue(const QString &group,
 | 
			
		||||
                                          const QString &valueKey,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										101
									
								
								src/launchoptions.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/launchoptions.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 | 
			
		||||
//
 | 
			
		||||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "global.h"
 | 
			
		||||
#include "launchoptions.h"
 | 
			
		||||
 | 
			
		||||
QStringList generateCommand(const QVariantMap &props) noexcept
 | 
			
		||||
{
 | 
			
		||||
    std::vector<std::unique_ptr<LaunchOption>> options;
 | 
			
		||||
    for (const auto &[key, value] : props.asKeyValueRange()) {
 | 
			
		||||
        if (key == setUserLaunchOption::key()) {
 | 
			
		||||
            options.push_back(std::make_unique<setUserLaunchOption>(value));
 | 
			
		||||
        } else if (key == setEnvLaunchOption::key()) {
 | 
			
		||||
            options.push_back(std::make_unique<setEnvLaunchOption>(value));
 | 
			
		||||
        } else {
 | 
			
		||||
            qWarning() << "unsupported options" << key;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    options.push_back(std::make_unique<splitLaunchOption>());
 | 
			
		||||
 | 
			
		||||
    std::sort(options.begin(),
 | 
			
		||||
              options.end(),
 | 
			
		||||
              [](const std::unique_ptr<LaunchOption> &lOption, const std::unique_ptr<LaunchOption> &rOption) {
 | 
			
		||||
                  if (lOption->type() == AppExecOption and rOption->type() == systemdOption) {
 | 
			
		||||
                      return false;
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  if (lOption->type() == AppExecOption and rOption->type() == splitOption) {
 | 
			
		||||
                      return false;
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  if (lOption->type() == splitOption and rOption->type() == systemdOption) {
 | 
			
		||||
                      return false;
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  return true;
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
    QStringList ret;
 | 
			
		||||
    std::for_each(options.begin(), options.end(), [&ret](const std::unique_ptr<LaunchOption> &option) {
 | 
			
		||||
        auto str = option->generateCommandLine();
 | 
			
		||||
        if (!str.isEmpty()) {
 | 
			
		||||
            ret.append(std::move(str));
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList setUserLaunchOption::generateCommandLine() const noexcept
 | 
			
		||||
{
 | 
			
		||||
    QStringList ret;
 | 
			
		||||
 | 
			
		||||
    bool ok{false};
 | 
			
		||||
    auto uid = m_val.toUInt(&ok);
 | 
			
		||||
    if (!ok) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto curUID = getCurrentUID();
 | 
			
		||||
 | 
			
		||||
    if (uid == curUID) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret.append("pkexec");
 | 
			
		||||
    ret.append("--user");
 | 
			
		||||
 | 
			
		||||
    struct passwd *destUser = getpwuid(uid);
 | 
			
		||||
    QString userName = destUser->pw_name;
 | 
			
		||||
    ret.append(userName);
 | 
			
		||||
 | 
			
		||||
    struct passwd *curUser = getpwuid(curUID);
 | 
			
		||||
    ret.append("env");
 | 
			
		||||
    ret.append("DISPLAY=:0");
 | 
			
		||||
 | 
			
		||||
    auto authFile = qgetenv("XAUTHORITY");
 | 
			
		||||
    ret.append(QString{"XAUTHORITY=%1"}.arg(authFile));
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList splitLaunchOption::generateCommandLine() const noexcept
 | 
			
		||||
{
 | 
			
		||||
    return QStringList{m_val.toString()};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList setEnvLaunchOption::generateCommandLine() const noexcept
 | 
			
		||||
{
 | 
			
		||||
    auto str = m_val.toString();
 | 
			
		||||
    if (str.isEmpty()) {
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return QStringList{QString{"--Environment=%1"}.arg(str)};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								src/launchoptions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/launchoptions.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,73 @@
 | 
			
		||||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 | 
			
		||||
//
 | 
			
		||||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <QVariantMap>
 | 
			
		||||
#include "constant.h"
 | 
			
		||||
 | 
			
		||||
struct LaunchOption
 | 
			
		||||
{
 | 
			
		||||
    explicit LaunchOption(QVariant v)
 | 
			
		||||
        : m_val(std::move(v))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    virtual ~LaunchOption() = default;
 | 
			
		||||
    [[nodiscard]] virtual QStringList generateCommandLine() const noexcept = 0;
 | 
			
		||||
    [[nodiscard]] static const QString &key() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        static QString none;
 | 
			
		||||
        return none;
 | 
			
		||||
    };
 | 
			
		||||
    [[nodiscard]] virtual const QString &type() const noexcept = 0;
 | 
			
		||||
 | 
			
		||||
    QVariant m_val;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct setUserLaunchOption : public LaunchOption
 | 
			
		||||
{
 | 
			
		||||
    using LaunchOption::LaunchOption;
 | 
			
		||||
    [[nodiscard]] const QString &type() const noexcept override
 | 
			
		||||
    {
 | 
			
		||||
        static QString tp{AppExecOption};
 | 
			
		||||
        return tp;
 | 
			
		||||
    }
 | 
			
		||||
    [[nodiscard]] static const QString &key() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        static QString uid{"uid"};
 | 
			
		||||
        return uid;
 | 
			
		||||
    }
 | 
			
		||||
    [[nodiscard]] QStringList generateCommandLine() const noexcept override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct setEnvLaunchOption : public LaunchOption
 | 
			
		||||
{
 | 
			
		||||
    using LaunchOption::LaunchOption;
 | 
			
		||||
    [[nodiscard]] const QString &type() const noexcept override
 | 
			
		||||
    {
 | 
			
		||||
        static QString tp{systemdOption};
 | 
			
		||||
        return tp;
 | 
			
		||||
    }
 | 
			
		||||
    [[nodiscard]] static const QString &key() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        static QString env{"env"};
 | 
			
		||||
        return env;
 | 
			
		||||
    }
 | 
			
		||||
    [[nodiscard]] QStringList generateCommandLine() const noexcept override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct splitLaunchOption : public LaunchOption
 | 
			
		||||
{
 | 
			
		||||
    splitLaunchOption()
 | 
			
		||||
        : LaunchOption(QString{"--"})
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] const QString &type() const noexcept override
 | 
			
		||||
    {
 | 
			
		||||
        static QString tp{splitOption};
 | 
			
		||||
        return tp;
 | 
			
		||||
    }
 | 
			
		||||
    [[nodiscard]] QStringList generateCommandLine() const noexcept override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
QStringList generateCommand(const QVariantMap &props) noexcept;
 | 
			
		||||
		Reference in New Issue
	
	Block a user