2014-11-13 01:04:59 +02:00
|
|
|
/* This file is part of the KDE libraries
|
|
|
|
Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
|
|
|
|
Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ktoolinvocation.h"
|
|
|
|
#include "kdebug.h"
|
|
|
|
#include "kglobal.h"
|
|
|
|
#include "kstandarddirs.h"
|
|
|
|
#include "kcomponentdata.h"
|
|
|
|
#include "kurl.h"
|
|
|
|
#include "kservice.h"
|
2022-05-24 02:40:12 +03:00
|
|
|
#include "klocale.h"
|
2022-10-03 16:25:13 +03:00
|
|
|
#include "kglobalsettings.h"
|
2023-07-31 08:08:59 +00:00
|
|
|
#include "kstartupinfo.h"
|
2014-11-13 01:04:59 +02:00
|
|
|
|
2015-09-27 01:19:30 +00:00
|
|
|
#include <QtCore/QThread>
|
|
|
|
#include <QtCore/QProcess>
|
|
|
|
#include <QtCore/QCoreApplication>
|
|
|
|
#include <QtDBus/QDBusInterface>
|
|
|
|
#include <QtDBus/QDBusConnectionInterface>
|
2023-07-31 08:08:59 +00:00
|
|
|
#include <QtGui/QX11Info>
|
|
|
|
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
# include <X11/Xlib.h>
|
|
|
|
# include <fixx11h.h>
|
|
|
|
#endif
|
2014-11-13 01:04:59 +02:00
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
#define KTOOLINVOCATION_TIMEOUT 250
|
|
|
|
|
|
|
|
// NOTE: keep in sync with:
|
|
|
|
// kdelibs/kinit/klauncher_adaptor.h
|
|
|
|
static inline QString getKLauncherError(const int result, const QString &app)
|
|
|
|
{
|
|
|
|
switch (result) {
|
|
|
|
case -1: {
|
|
|
|
return i18n("Application service is not valid or does not support multiple files: %1.", app);
|
|
|
|
}
|
|
|
|
case -2: {
|
|
|
|
return i18n("Application not found: %1.", app);
|
|
|
|
}
|
|
|
|
case -3: {
|
|
|
|
return i18n("Application could not be processed: %1.", app);
|
|
|
|
}
|
|
|
|
case -4: {
|
|
|
|
return i18n("Application failed to start: %1.", app);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i18n("Unknown KLauncher error for application: %1.", app);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void printError(const QString &text, QString *error)
|
2022-12-08 06:35:30 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
if (error) {
|
2022-12-08 06:35:30 +02:00
|
|
|
*error = text;
|
2024-05-09 00:55:08 +03:00
|
|
|
} else {
|
2022-12-08 06:35:30 +02:00
|
|
|
kError() << text;
|
2024-05-09 00:55:08 +03:00
|
|
|
}
|
2022-12-08 06:35:30 +02:00
|
|
|
}
|
|
|
|
|
2024-05-09 00:55:08 +03:00
|
|
|
K_GLOBAL_STATIC(KToolInvocation, kToolInvocation)
|
|
|
|
|
|
|
|
KToolInvocation* KToolInvocation::self()
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
return kToolInvocation;
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2024-05-09 00:55:08 +03:00
|
|
|
KToolInvocation::KToolInvocation(QObject *parent)
|
|
|
|
: QObject(parent),
|
2022-10-27 08:20:33 +03:00
|
|
|
klauncherIface(nullptr)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2022-12-19 12:41:17 +02:00
|
|
|
klauncherIface = new QDBusInterface(
|
2022-10-27 08:20:33 +03:00
|
|
|
QString::fromLatin1("org.kde.klauncher"),
|
|
|
|
QString::fromLatin1("/KLauncher"),
|
2022-12-19 12:41:17 +02:00
|
|
|
QString::fromLatin1("org.kde.KLauncher"),
|
|
|
|
QDBusConnection::sessionBus(),
|
|
|
|
this
|
2022-10-27 08:20:33 +03:00
|
|
|
);
|
2024-05-09 00:55:08 +03:00
|
|
|
qAddPostRoutine(kToolInvocation.destroy);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
KToolInvocation::~KToolInvocation()
|
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
qRemovePostRoutine(kToolInvocation.destroy);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-12-08 06:35:30 +02:00
|
|
|
void KToolInvocation::setLaunchEnv(const QString &name, const QString &value)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
klauncherIface->asyncCall(QString::fromLatin1("setLaunchEnv"), name, value);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int KToolInvocation::startServiceInternal(const char *_function,
|
2022-12-19 12:41:17 +02:00
|
|
|
const QString &name, const QStringList &URLs,
|
|
|
|
QString *error,
|
2022-12-20 15:40:32 +02:00
|
|
|
const QByteArray &startup_id,
|
2022-12-19 12:41:17 +02:00
|
|
|
const QString &workdir)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2022-09-23 09:13:19 +03:00
|
|
|
QString function = QString::fromLatin1(_function);
|
2014-11-13 01:04:59 +02:00
|
|
|
// make sure there is id, so that user timestamp exists
|
|
|
|
QStringList envs;
|
2023-07-31 08:08:59 +00:00
|
|
|
if (QX11Info::display()) {
|
|
|
|
const QString dpystring = QString::fromLatin1(XDisplayString(QX11Info::display()));
|
|
|
|
envs << QLatin1String("DISPLAY=") + dpystring;
|
|
|
|
} else {
|
|
|
|
const QString dpystring = QString::fromLocal8Bit(qgetenv("DISPLAY"));
|
|
|
|
if (!dpystring.isEmpty()) {
|
|
|
|
envs << QLatin1String("DISPLAY=") + dpystring;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
QDBusPendingReply<int> reply;
|
|
|
|
if (qstrcmp(_function, "kdeinit_exec_with_workdir") == 0) {
|
|
|
|
reply = klauncherIface->asyncCall(
|
2023-09-03 01:46:51 +03:00
|
|
|
function, name, URLs, envs, QString::fromLatin1(startup_id, startup_id.size()), workdir
|
2022-12-19 12:41:17 +02:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
reply = klauncherIface->asyncCall(
|
2023-09-03 01:46:51 +03:00
|
|
|
function, name, URLs, envs, QString::fromLatin1(startup_id, startup_id.size())
|
2022-12-19 12:41:17 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
kDebug() << "Waiting for klauncher call to finish" << function;
|
|
|
|
while (!reply.isFinished()) {
|
|
|
|
QCoreApplication::processEvents(QEventLoop::AllEvents, KTOOLINVOCATION_TIMEOUT);
|
|
|
|
}
|
|
|
|
kDebug() << "Done waiting for klauncher call to finish" << function;
|
|
|
|
if (!reply.isValid()) {
|
|
|
|
printError(
|
|
|
|
i18n("KLauncher error: %1.", reply.error().message()),
|
|
|
|
error
|
|
|
|
);
|
2014-11-13 01:04:59 +02:00
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
const int result = reply.value();
|
|
|
|
if (result < 0) {
|
|
|
|
printError(
|
|
|
|
getKLauncherError(result, name),
|
|
|
|
error
|
|
|
|
);
|
|
|
|
// compat
|
|
|
|
return -result;
|
|
|
|
} else if (result != 0) {
|
|
|
|
printError(
|
|
|
|
i18n("Application failed to start: %1.", name),
|
|
|
|
error
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return result;
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
int KToolInvocation::startServiceByDesktopPath(const QString &name, const QString &URL,
|
2024-05-09 00:55:08 +03:00
|
|
|
QString *error, const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
|
|
|
QStringList URLs;
|
2024-05-09 00:55:08 +03:00
|
|
|
if (!URL.isEmpty()) {
|
2014-11-13 01:04:59 +02:00
|
|
|
URLs.append(URL);
|
2024-05-09 00:55:08 +03:00
|
|
|
}
|
|
|
|
return startServiceInternal("start_service_by_desktop_path", name, URLs, error, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
int KToolInvocation::startServiceByDesktopPath(const QString &name, const QStringList &URLs,
|
2024-05-09 00:55:08 +03:00
|
|
|
QString *error, const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
return startServiceInternal("start_service_by_desktop_path", name, URLs, error, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-12-19 16:53:33 +02:00
|
|
|
int KToolInvocation::startServiceByDesktopName(const QString &name, const QString &URL,
|
2024-05-09 00:55:08 +03:00
|
|
|
QString *error, const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
|
|
|
QStringList URLs;
|
2024-05-09 00:55:08 +03:00
|
|
|
if (!URL.isEmpty()) {
|
2014-11-13 01:04:59 +02:00
|
|
|
URLs.append(URL);
|
2024-05-09 00:55:08 +03:00
|
|
|
}
|
|
|
|
return startServiceInternal("start_service_by_desktop_name", name, URLs, error, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
int KToolInvocation::startServiceByDesktopName(const QString &name, const QStringList &URLs,
|
2024-05-09 00:55:08 +03:00
|
|
|
QString *error, const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
return startServiceInternal("start_service_by_desktop_name", name, URLs, error, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2024-05-09 00:55:08 +03:00
|
|
|
int KToolInvocation::kdeinitExec(const QString &name, const QStringList &args, QString *error,
|
2022-12-19 12:41:17 +02:00
|
|
|
const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
return startServiceInternal("kdeinit_exec", name, args, error, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-05-09 00:55:08 +03:00
|
|
|
int KToolInvocation::kdeinitExecWait(const QString &name, const QStringList &args, QString *error,
|
2022-12-19 12:41:17 +02:00
|
|
|
const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
return startServiceInternal("kdeinit_exec_wait", name, args, error, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-12-19 12:41:17 +02:00
|
|
|
void KToolInvocation::invokeHelp(const QString &anchor,
|
|
|
|
const QString &_appname,
|
|
|
|
const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
|
|
|
KUrl url;
|
|
|
|
QString appname;
|
|
|
|
QString docPath;
|
|
|
|
if (_appname.isEmpty()) {
|
2023-06-19 01:12:54 +03:00
|
|
|
appname = QCoreApplication::applicationName();
|
2022-10-03 16:03:50 +03:00
|
|
|
} else {
|
2014-11-13 01:04:59 +02:00
|
|
|
appname = _appname;
|
2022-10-03 16:03:50 +03:00
|
|
|
}
|
2014-11-13 01:04:59 +02:00
|
|
|
KService::Ptr service(KService::serviceByDesktopName(appname));
|
|
|
|
if (service) {
|
|
|
|
docPath = service->docPath();
|
|
|
|
}
|
|
|
|
if (!docPath.isEmpty()) {
|
2022-10-03 16:25:13 +03:00
|
|
|
url = KUrl(KUrl(QString::fromLatin1(KDE_HELP_URL)), docPath);
|
2014-11-13 01:04:59 +02:00
|
|
|
} else {
|
2022-10-03 16:25:13 +03:00
|
|
|
url = QString::fromLatin1(KDE_HELP_URL);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
if (!anchor.isEmpty()) {
|
|
|
|
url.addQueryItem(QString::fromLatin1("anchor"), anchor);
|
|
|
|
}
|
2016-05-14 10:27:17 +00:00
|
|
|
invokeBrowser(url.url());
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2024-05-09 00:55:08 +03:00
|
|
|
void KToolInvocation::invokeMailer(const QString &address, const QString &subject,
|
|
|
|
const QByteArray &startup_id)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
2024-05-09 00:55:08 +03:00
|
|
|
invokeMailer(address, QString(), subject, QString(), QStringList(), startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2024-05-09 00:55:08 +03:00
|
|
|
void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray &startup_id,
|
|
|
|
bool allowAttachments)
|
2014-11-13 01:04:59 +02:00
|
|
|
{
|
|
|
|
QString address = mailtoURL.path();
|
|
|
|
QString subject;
|
|
|
|
QString cc;
|
|
|
|
QString body;
|
|
|
|
|
|
|
|
const QStringList queries = mailtoURL.query().mid(1).split(QLatin1Char('&'));
|
|
|
|
const QChar comma = QChar::fromLatin1(',');
|
|
|
|
QStringList attachURLs;
|
|
|
|
for (QStringList::ConstIterator it = queries.begin(); it != queries.end(); ++it)
|
|
|
|
{
|
|
|
|
QString q = (*it).toLower();
|
|
|
|
if (q.startsWith(QLatin1String("subject=")))
|
|
|
|
subject = KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
|
|
|
|
else
|
|
|
|
if (q.startsWith(QLatin1String("cc=")))
|
|
|
|
cc = cc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): cc + comma + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
|
|
|
|
else
|
2022-10-15 12:54:40 +03:00
|
|
|
if (q.startsWith(QLatin1String("body=")))
|
|
|
|
body = KUrl::fromPercentEncoding((*it).mid(5).toLatin1());
|
2014-11-13 01:04:59 +02:00
|
|
|
else
|
2022-10-15 12:54:40 +03:00
|
|
|
if (allowAttachments && q.startsWith(QLatin1String("attach=")))
|
|
|
|
attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(7).toLatin1()));
|
2014-11-13 01:04:59 +02:00
|
|
|
else
|
2022-10-15 12:54:40 +03:00
|
|
|
if (allowAttachments && q.startsWith(QLatin1String("attachment=")))
|
|
|
|
attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(11).toLatin1()));
|
2014-11-13 01:04:59 +02:00
|
|
|
else
|
2022-10-15 12:54:40 +03:00
|
|
|
if (q.startsWith(QLatin1String("to=")))
|
|
|
|
address = address.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): address + comma + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2022-10-15 12:54:40 +03:00
|
|
|
invokeMailer(address, cc, subject, body, attachURLs, startup_id);
|
2014-11-13 01:04:59 +02:00
|
|
|
}
|
|
|
|
|
2015-02-27 07:40:26 +00:00
|
|
|
#include "moc_ktoolinvocation.cpp"
|