kinit: upload modified temporary files

NOTE: this is potentionally dangerous thing to do because KLauncher reaps
processes and there is no interruption point for it right now which is one
of the reasons upload confirmation is not in place (user interaction will
have to be potentionally canceled too)

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-05-24 14:08:42 +03:00
parent 06654c0495
commit 1cb8619539
2 changed files with 41 additions and 12 deletions

View file

@ -94,13 +94,15 @@ KLauncherProcess::~KLauncherProcess()
void KLauncherProcess::setupProcess(const QString &appexe, const QStringList &args,
const quint64 window, const KService::Ptr kservice,
const qint64 timeout, const bool temp)
const qint64 timeout, const bool temp,
const KLauncherDownloads &downloaded)
{
Q_ASSERT(m_kstartupinfoid.none() == true);
m_appexe = appexe;
m_args = args;
m_window = window;
m_temp = temp;
m_downloaded = downloaded;
QByteArray startupwmclass;
if (KRun::checkStartupNotify(kservice.data(), &startupwmclass)) {
m_kstartupinfoid.initId(KStartupInfo::createNewStartupId());
@ -118,6 +120,11 @@ void KLauncherProcess::setupProcess(const QString &appexe, const QStringList &ar
} else {
kDebug() << "no ASN for" << m_appexe;
}
foreach (const QString &download, m_downloaded.keys()) {
const QDateTime downloadlastmodified = QFileInfo(download).lastModified();
kDebug() << "current last modified for" << download << "is" << downloadlastmodified;
m_lastmodified.insert(download, downloadlastmodified);
}
}
void KLauncherProcess::slotProcessStateChanged(QProcess::ProcessState state)
@ -143,6 +150,20 @@ void KLauncherProcess::slotProcessStateChanged(QProcess::ProcessState state)
);
}
}
if (!m_downloaded.isEmpty()) {
foreach (const QString &download, m_downloaded.keys()) {
const QDateTime downloadlastmodified = QFileInfo(download).lastModified();
kDebug() << "current last modified for" << download << "is" << downloadlastmodified;
if (downloadlastmodified != m_lastmodified.value(download)) {
// TODO: maybe ask
const KUrl uploadurl = m_downloaded.value(download);
kDebug() << "uploading" << download << "to" << uploadurl;
if (!KIO::NetAccess::upload(download, uploadurl, findWindow(m_window))) {
kWarning() << "could not upload" << download;
}
}
}
}
QTimer::singleShot(s_deletedelay, this, SLOT(deleteLater()));
}
}
@ -354,10 +375,9 @@ bool KLauncherAdaptor::start_service_by_storage_id(const QString &serviceName,
}
const QString program = programandargs.takeFirst();
const QString kserviceexec = kservice->exec();
KLauncherDownloads downloaded;
if (!kserviceexec.contains(QLatin1String("%u")) && !kserviceexec.contains(QLatin1String("%U"))) {
kDebug() << "service does not support remote" << serviceName;
// TODO: upload? spec says nothing
QStringList downloaded;
foreach (const QString &url, urls) {
const KUrl realurl = KUrl(url);
if (!realurl.isLocalFile()) {
@ -368,13 +388,13 @@ bool KLauncherAdaptor::start_service_by_storage_id(const QString &serviceName,
const QString prettyurl = realurl.prettyUrl();
if (!KIO::NetAccess::download(realurl, urldestination, findWindow(window))) {
kError() << "could not download" << prettyurl;
showError(i18n("Could not download URL: %1", Qt::escape(prettyurl)), window);
showError(i18n("Could not download URL: %1", prettyurl), window);
removeTemp(temp, urls);
removeTemp(true, downloaded);
removeTemp(true, downloaded.keys());
return false;
}
kDebug() << "downloaded" << prettyurl << "to" << urldestination;
downloaded.append(urldestination);
downloaded.insert(urldestination, realurl);
// URLs may not be unique
int indexofurl = programandargs.indexOf(url);
while (indexofurl != -1) {
@ -386,7 +406,7 @@ bool KLauncherAdaptor::start_service_by_storage_id(const QString &serviceName,
temp = (temp || !downloaded.isEmpty());
}
kDebug() << "starting" << kservice->entryPath() << urls;
return startProgram(program, programandargs, envs, window, temp, programworkdir, m_startuptimeout, kservice);
return startProgram(program, programandargs, envs, window, temp, programworkdir, m_startuptimeout, kservice, downloaded);
}
bool KLauncherAdaptor::start_service_by_url(const QString &url, const QStringList &envs,
@ -429,7 +449,7 @@ bool KLauncherAdaptor::start_service_by_url(const QString &url, const QStringLis
kDebug() << "execuable file" << url;
KMessageBox::sorryWId(
static_cast<WId>(window),
i18n("The file <tt>%1</tt> is an executable program.<br/>For safety it will not be started.", Qt::escape(realurl.prettyUrl()))
i18n("The file <tt>%1</tt> is an executable program.<br/>For safety it will not be started.", realurl.prettyUrl())
);
removeTemp(temp, QStringList() << url);
return false;
@ -496,7 +516,8 @@ void KLauncherAdaptor::startDetached(const QString &name, const QStringList &arg
bool KLauncherAdaptor::startProgram(const QString &app, const QStringList &args, const QStringList &envs,
const quint64 window, const bool temp, const QString &workdir,
const qint64 timeout, const KService::Ptr kservice)
const qint64 timeout, const KService::Ptr kservice,
const KLauncherDownloads &downloaded)
{
const QString appexe = findExe(app);
if (appexe.isEmpty()) {
@ -522,7 +543,7 @@ bool KLauncherAdaptor::startProgram(const QString &app, const QStringList &args,
}
process->setProcessEnvironment(processenv);
process->setWorkingDirectory(workdir);
process->setupProcess(appexe, args, window, kservice, timeout, temp);
process->setupProcess(appexe, args, window, kservice, timeout, temp, downloaded);
kDebug() << "starting" << appexe << args << envs << workdir;
process->start(appexe, args);
while (process->state() == QProcess::Starting) {

View file

@ -21,13 +21,17 @@
#include "kstartupinfo.h"
#include "kservice.h"
#include "kurl.h"
#include <QDBusAbstractAdaptor>
#include <QProcess>
#include <QTimer>
#include <QMap>
// #define KLAUNCHER_DEBUG
typedef QMap<QString,KUrl> KLauncherDownloads;
class KLauncherProcess : public QProcess
{
Q_OBJECT
@ -36,7 +40,8 @@ public:
~KLauncherProcess();
void setupProcess(const QString &appexe, const QStringList &args, const quint64 window,
const KService::Ptr kservice, const qint64 timeout, const bool temp);
const KService::Ptr kservice, const qint64 timeout, const bool temp,
const KLauncherDownloads &downloaded);
private Q_SLOTS:
void slotProcessStateChanged(QProcess::ProcessState state);
@ -58,6 +63,8 @@ private:
QStringList m_args;
quint64 m_window;
bool m_temp;
KLauncherDownloads m_downloaded;
QMap<QString,QDateTime> m_lastmodified;
};
// Adaptor class for interface org.kde.KLauncher
@ -107,7 +114,8 @@ private:
void startDetached(const QString &name, const QStringList &args);
bool startProgram(const QString &app, const QStringList &args, const QStringList &envs,
const quint64 window, const bool temp, const QString &workdir,
const qint64 timeout, const KService::Ptr kservice = KService::Ptr(nullptr));
const qint64 timeout, const KService::Ptr kservice = KService::Ptr(nullptr),
const KLauncherDownloads &downloaded = KLauncherDownloads());
QProcessEnvironment m_environment;
qint64 m_startuptimeout;