WIP: port to polkit
This commit is contained in:
parent
08c1acb6b4
commit
edfabb90dc
|
@ -39,6 +39,7 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
include(ECMSetupVersion)
|
include(ECMSetupVersion)
|
||||||
|
include(ECMConfiguredInstall)
|
||||||
|
|
||||||
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
|
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
|
||||||
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h"
|
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h"
|
||||||
|
|
|
@ -23,6 +23,9 @@ qt5_generate_dbus_interface(
|
||||||
OPTIONS -a
|
OPTIONS -a
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
find_package(PolkitQt5-1 REQUIRED)
|
||||||
|
|
||||||
qt5_add_dbus_interface(ApplicationInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${application_interface_xml} externalcommand_interface)
|
qt5_add_dbus_interface(ApplicationInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${application_interface_xml} externalcommand_interface)
|
||||||
qt5_add_dbus_interface(HelperInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${helper_interface_xml} externalcommandhelper_interface)
|
qt5_add_dbus_interface(HelperInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${helper_interface_xml} externalcommandhelper_interface)
|
||||||
|
|
||||||
|
@ -57,11 +60,15 @@ target_link_libraries(kpmcore_externalcommand
|
||||||
Qt5::DBus
|
Qt5::DBus
|
||||||
KF5::AuthCore
|
KF5::AuthCore
|
||||||
KF5::I18n
|
KF5::I18n
|
||||||
|
PolkitQt5-1::Core
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
install(TARGETS kpmcore_externalcommand DESTINATION ${KDE_INSTALL_LIBEXECDIR})
|
||||||
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
||||||
install( FILES util/org.kde.kpmcore.applicationinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
install( FILES util/org.kde.kpmcore.applicationinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
||||||
|
|
||||||
kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root)
|
|
||||||
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
||||||
|
ecm_install_configured_files(
|
||||||
|
INPUT util/org.kde.kpmcore.helperinterface.service.in
|
||||||
|
DESTINATION ${KDE_INSTALL_DBUSDIR}/system-services
|
||||||
|
)
|
||||||
|
|
|
@ -49,7 +49,6 @@ struct ExternalCommandPrivate
|
||||||
int m_ExitCode;
|
int m_ExitCode;
|
||||||
QByteArray m_Output;
|
QByteArray m_Output;
|
||||||
QByteArray m_Input;
|
QByteArray m_Input;
|
||||||
DBusThread *m_thread;
|
|
||||||
QProcess::ProcessChannelMode processChannelMode;
|
QProcess::ProcessChannelMode processChannelMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,9 +70,9 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co
|
||||||
d->m_ExitCode = -1;
|
d->m_ExitCode = -1;
|
||||||
d->m_Output = QByteArray();
|
d->m_Output = QByteArray();
|
||||||
|
|
||||||
if (!helperStarted)
|
// if (!helperStarted)
|
||||||
if(!startHelper())
|
// if(!startHelper())
|
||||||
Log(Log::Level::error) << xi18nc("@info:status", "Could not obtain administrator privileges.");
|
// Log(Log::Level::error) << xi18nc("@info:status", "Could not obtain administrator privileges.");
|
||||||
|
|
||||||
d->processChannelMode = processChannelMode;
|
d->processChannelMode = processChannelMode;
|
||||||
}
|
}
|
||||||
|
@ -129,6 +128,8 @@ bool ExternalCommand::start(int timeout)
|
||||||
if (cmd.isEmpty())
|
if (cmd.isEmpty())
|
||||||
cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") });
|
cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") });
|
||||||
|
|
||||||
|
qDebug() << "start";
|
||||||
|
|
||||||
auto interface = helperInterface();
|
auto interface = helperInterface();
|
||||||
if (!interface)
|
if (!interface)
|
||||||
return false;
|
return false;
|
||||||
|
@ -231,7 +232,7 @@ OrgKdeKpmcoreExternalcommandInterface* ExternalCommand::helperInterface()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"),
|
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.helperinterface"),
|
||||||
QStringLiteral("/Helper"), QDBusConnection::systemBus(), this);
|
QStringLiteral("/Helper"), QDBusConnection::systemBus(), this);
|
||||||
interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
||||||
return interface;
|
return interface;
|
||||||
|
@ -355,46 +356,14 @@ bool ExternalCommand::startHelper()
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
d->m_thread = new DBusThread;
|
qDebug() <<"starting helper";
|
||||||
d->m_thread->start();
|
|
||||||
|
|
||||||
KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init"));
|
|
||||||
action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand"));
|
|
||||||
action.setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
|
||||||
action.setParentWidget(parent);
|
|
||||||
QVariantMap arguments;
|
|
||||||
action.setArguments(arguments);
|
|
||||||
m_job = action.execute();
|
|
||||||
m_job->start();
|
|
||||||
|
|
||||||
// Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop)
|
|
||||||
QEventLoop loop;
|
|
||||||
auto exitLoop = [&] () { loop.exit(); };
|
|
||||||
auto conn = QObject::connect(m_job, &KAuth::ExecuteJob::newData, exitLoop);
|
|
||||||
QObject::connect(m_job, &KJob::finished, [=] () { if(m_job->error()) exitLoop(); } );
|
|
||||||
loop.exec();
|
|
||||||
QObject::disconnect(conn);
|
|
||||||
|
|
||||||
helperStarted = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalCommand::stopHelper()
|
void ExternalCommand::stopHelper()
|
||||||
{
|
{
|
||||||
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"),
|
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.helperinterface"),
|
||||||
QStringLiteral("/Helper"), QDBusConnection::systemBus());
|
QStringLiteral("/Helper"), QDBusConnection::systemBus());
|
||||||
interface->exit();
|
interface->exit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBusThread::run()
|
|
||||||
{
|
|
||||||
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface")) ||
|
|
||||||
!QDBusConnection::systemBus().registerObject(QStringLiteral("/Application"), this, QDBusConnection::ExportAllSlots)) {
|
|
||||||
qWarning() << QDBusConnection::systemBus().lastError().message();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QEventLoop loop;
|
|
||||||
loop.exec();
|
|
||||||
}
|
|
||||||
|
|
|
@ -36,15 +36,6 @@ class OrgKdeKpmcoreExternalcommandInterface;
|
||||||
|
|
||||||
struct ExternalCommandPrivate;
|
struct ExternalCommandPrivate;
|
||||||
|
|
||||||
class DBusThread : public QThread
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
// We register on DBus so the helper can monitor us and terminate if we
|
|
||||||
// terminate.
|
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.applicationinterface")
|
|
||||||
void run() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** An external command.
|
/** An external command.
|
||||||
|
|
||||||
Runs an external command as a child process.
|
Runs an external command as a child process.
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "externalcommand_whitelist.h"
|
#include "externalcommand_whitelist.h"
|
||||||
|
|
||||||
#include <QtDBus>
|
#include <QtDBus>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
@ -21,6 +22,10 @@
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
#include <PolkitQt1/Authority>
|
||||||
|
#include <PolkitQt1/Subject>
|
||||||
|
|
||||||
|
#include <polkitqt1-version.h>
|
||||||
|
|
||||||
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
||||||
*
|
*
|
||||||
|
@ -35,52 +40,34 @@
|
||||||
* This helper also starts another DBus interface where it listens to
|
* This helper also starts another DBus interface where it listens to
|
||||||
* command execution requests from the application that started the helper.
|
* command execution requests from the application that started the helper.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* DAVE - this all needs updating
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
ActionReply ExternalCommandHelper::init(const QVariantMap& args)
|
|
||||||
|
ExternalCommandHelper::ExternalCommandHelper()
|
||||||
{
|
{
|
||||||
Q_UNUSED(args)
|
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots)) {
|
||||||
|
::exit(-1);
|
||||||
ActionReply reply;
|
|
||||||
|
|
||||||
if (!QDBusConnection::systemBus().isConnected() || !QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface")) ||
|
|
||||||
!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots)) {
|
|
||||||
qWarning() << QDBusConnection::systemBus().lastError().message();
|
|
||||||
reply.addData(QStringLiteral("success"), false);
|
|
||||||
|
|
||||||
// Also end the application loop started by KAuth's main() code. Our loop
|
|
||||||
// exits when our client disappears. Without client we have no reason to
|
|
||||||
// live.
|
|
||||||
qApp->quit();
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_loop = std::make_unique<QEventLoop>();
|
|
||||||
HelperSupport::progressStep(QVariantMap());
|
|
||||||
|
|
||||||
// End the loop and return only once the client is done using us.
|
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
|
||||||
auto serviceWatcher =
|
::exit(-1);
|
||||||
new QDBusServiceWatcher(QStringLiteral("org.kde.kpmcore.applicationinterface"),
|
}
|
||||||
QDBusConnection::systemBus(),
|
|
||||||
QDBusServiceWatcher::WatchForUnregistration,
|
// we know this service must be registered already as DBus policy blocks calls from anyone else
|
||||||
this);
|
m_serviceWatcher = new QDBusServiceWatcher(this);
|
||||||
connect(serviceWatcher, &QDBusServiceWatcher::serviceUnregistered,
|
m_serviceWatcher->setConnection(QDBusConnection ::systemBus());
|
||||||
[this]() {
|
m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
||||||
m_loop->exit();
|
|
||||||
|
connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, qApp, [this](const QString &service) {
|
||||||
|
m_serviceWatcher->removeWatchedService(service);
|
||||||
|
if (m_serviceWatcher->watchedServices().isEmpty()) {
|
||||||
|
qApp->quit();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
m_loop->exec();
|
|
||||||
reply.addData(QStringLiteral("success"), true);
|
|
||||||
|
|
||||||
// Also end the application loop started by KAuth's main() code. Our loop
|
|
||||||
// exits when our client disappears. Without client we have no reason to
|
|
||||||
// live.
|
|
||||||
qApp->quit();
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Reads the given number of bytes from the sourceDevice into the given buffer.
|
/** Reads the given number of bytes from the sourceDevice into the given buffer.
|
||||||
@param sourceDevice device or file to read from
|
@param sourceDevice device or file to read from
|
||||||
@param buffer buffer to store the bytes read in
|
@param buffer buffer to store the bytes read in
|
||||||
|
@ -148,6 +135,9 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr
|
||||||
*/
|
*/
|
||||||
bool ExternalCommandHelper::createFile(const QString &filePath, const QByteArray& fileContents)
|
bool ExternalCommandHelper::createFile(const QString &filePath, const QByteArray& fileContents)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
QFile device(filePath);
|
QFile device(filePath);
|
||||||
|
|
||||||
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
|
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
|
||||||
|
@ -167,6 +157,9 @@ bool ExternalCommandHelper::createFile(const QString &filePath, const QByteArray
|
||||||
// If targetDevice is empty then return QByteArray with data that was read from disk.
|
// If targetDevice is empty then return QByteArray with data that was read from disk.
|
||||||
QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
|
QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return QVariantMap();
|
||||||
|
}
|
||||||
QVariantMap reply;
|
QVariantMap reply;
|
||||||
reply[QStringLiteral("success")] = true;
|
reply[QStringLiteral("success")] = true;
|
||||||
|
|
||||||
|
@ -256,6 +249,9 @@ QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const
|
||||||
|
|
||||||
bool ExternalCommandHelper::writeData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte)
|
bool ExternalCommandHelper::writeData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Do not allow using this helper for writing to arbitrary location
|
// Do not allow using this helper for writing to arbitrary location
|
||||||
if ( targetDevice.left(5) != QStringLiteral("/dev/") )
|
if ( targetDevice.left(5) != QStringLiteral("/dev/") )
|
||||||
return false;
|
return false;
|
||||||
|
@ -265,6 +261,9 @@ bool ExternalCommandHelper::writeData(const QByteArray& buffer, const QString& t
|
||||||
|
|
||||||
bool ExternalCommandHelper::createFile(const QByteArray& fileContents, const QString& filePath)
|
bool ExternalCommandHelper::createFile(const QByteArray& fileContents, const QString& filePath)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Do not allow using this helper for writing to arbitrary location
|
// Do not allow using this helper for writing to arbitrary location
|
||||||
if ( !filePath.contains(QStringLiteral("/etc/fstab")) )
|
if ( !filePath.contains(QStringLiteral("/etc/fstab")) )
|
||||||
return false;
|
return false;
|
||||||
|
@ -274,6 +273,9 @@ bool ExternalCommandHelper::createFile(const QByteArray& fileContents, const QSt
|
||||||
|
|
||||||
QVariantMap ExternalCommandHelper::start(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
|
QVariantMap ExternalCommandHelper::start(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return QVariantMap();
|
||||||
|
}
|
||||||
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
||||||
QVariantMap reply;
|
QVariantMap reply;
|
||||||
reply[QStringLiteral("success")] = true;
|
reply[QStringLiteral("success")] = true;
|
||||||
|
@ -287,7 +289,7 @@ QVariantMap ExternalCommandHelper::start(const QString& command, const QStringLi
|
||||||
QString basename = command.mid(command.lastIndexOf(QLatin1Char('/')) + 1);
|
QString basename = command.mid(command.lastIndexOf(QLatin1Char('/')) + 1);
|
||||||
if (std::find(std::begin(allowedCommands), std::end(allowedCommands), basename) == std::end(allowedCommands)) {
|
if (std::find(std::begin(allowedCommands), std::end(allowedCommands), basename) == std::end(allowedCommands)) {
|
||||||
qInfo() << command <<" command is not one of the whitelisted command";
|
qInfo() << command <<" command is not one of the whitelisted command";
|
||||||
m_loop->exit();
|
qApp->quit();
|
||||||
reply[QStringLiteral("success")] = false;
|
reply[QStringLiteral("success")] = false;
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
@ -309,10 +311,10 @@ QVariantMap ExternalCommandHelper::start(const QString& command, const QStringLi
|
||||||
|
|
||||||
void ExternalCommandHelper::exit()
|
void ExternalCommandHelper::exit()
|
||||||
{
|
{
|
||||||
m_loop->exit();
|
if (!isCallerAuthorized()) {
|
||||||
|
return;
|
||||||
QDBusConnection::systemBus().unregisterObject(QStringLiteral("/Helper"));
|
}
|
||||||
QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"));
|
qApp->quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalCommandHelper::onReadOutput()
|
void ExternalCommandHelper::onReadOutput()
|
||||||
|
@ -331,4 +333,48 @@ void ExternalCommandHelper::onReadOutput()
|
||||||
*report() << QString::fromLocal8Bit(s);*/
|
*report() << QString::fromLocal8Bit(s);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
KAUTH_HELPER_MAIN("org.kde.kpmcore.externalcommand", ExternalCommandHelper)
|
bool ExternalCommandHelper::isCallerAuthorized()
|
||||||
|
{
|
||||||
|
if (!calledFromDBus()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// track who called into us so we can close when all callers have gone away
|
||||||
|
// this has to happen before authorisation as anyone could have activated us
|
||||||
|
m_serviceWatcher->addWatchedService(message().service());
|
||||||
|
|
||||||
|
PolkitQt1::SystemBusNameSubject subject(message().service());
|
||||||
|
PolkitQt1::Authority *authority = PolkitQt1::Authority::instance();
|
||||||
|
|
||||||
|
PolkitQt1::Authority::Result result;
|
||||||
|
QEventLoop e;
|
||||||
|
connect(authority, &PolkitQt1::Authority::checkAuthorizationFinished, [&result, &e](PolkitQt1::Authority::Result _result) {
|
||||||
|
result = _result;
|
||||||
|
e.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
authority->checkAuthorization(QStringLiteral("org.kde.kpmcore.externalcommand.init"), subject, PolkitQt1::Authority::AllowUserInteraction);
|
||||||
|
e.exec();
|
||||||
|
|
||||||
|
if (authority->hasError()) {
|
||||||
|
qDebug() << "Encountered error while checking authorization, error code:" << authority->lastError() << authority->errorDetails();
|
||||||
|
authority->clearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case PolkitQt1::Authority::Yes:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
sendErrorReply(QDBusError::AccessDenied);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
ExternalCommandHelper helper;
|
||||||
|
app.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "externalcommandhelper.moc"
|
||||||
|
|
|
@ -18,10 +18,13 @@
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QDBusContext>
|
||||||
|
|
||||||
|
class QDBusServiceWatcher;
|
||||||
|
|
||||||
using namespace KAuth;
|
using namespace KAuth;
|
||||||
|
|
||||||
class ExternalCommandHelper : public QObject
|
class ExternalCommandHelper : public QObject, public QDBusContext
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.externalcommand")
|
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.externalcommand")
|
||||||
|
@ -31,12 +34,12 @@ Q_SIGNALS:
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ExternalCommandHelper();
|
||||||
bool readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size);
|
bool readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size);
|
||||||
bool writeData(const QString& targetDevice, const QByteArray& buffer, const qint64 offset);
|
bool writeData(const QString& targetDevice, const QByteArray& buffer, const qint64 offset);
|
||||||
bool createFile(const QString& filePath, const QByteArray& fileContents);
|
bool createFile(const QString& filePath, const QByteArray& fileContents);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
ActionReply init(const QVariantMap& args);
|
|
||||||
Q_SCRIPTABLE QVariantMap start(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
|
Q_SCRIPTABLE QVariantMap start(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
|
||||||
Q_SCRIPTABLE QVariantMap copyblocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize);
|
Q_SCRIPTABLE QVariantMap copyblocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize);
|
||||||
Q_SCRIPTABLE bool writeData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte);
|
Q_SCRIPTABLE bool writeData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte);
|
||||||
|
@ -44,11 +47,12 @@ public Q_SLOTS:
|
||||||
Q_SCRIPTABLE void exit();
|
Q_SCRIPTABLE void exit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onReadOutput();
|
|
||||||
|
|
||||||
std::unique_ptr<QEventLoop> m_loop;
|
bool isCallerAuthorized();
|
||||||
|
|
||||||
|
void onReadOutput();
|
||||||
QProcess m_cmd;
|
QProcess m_cmd;
|
||||||
// QByteArray output;
|
QDBusServiceWatcher *m_serviceWatcher = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</policy>
|
</policy>
|
||||||
|
|
||||||
<policy context="default">
|
<policy context="default">
|
||||||
<allow send_destination="org.kde.kpmcore.externalcommand"
|
<allow send_destination="org.kde.kpmcore.helperinterface"
|
||||||
send_interface="org.kde.kpmcore.externalcommand"/>
|
send_interface="org.kde.kpmcore.externalcommand"/>
|
||||||
|
|
||||||
</policy>
|
</policy>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[D-BUS Service]
|
||||||
|
Name=org.kde.kpmcore.helperinterface
|
||||||
|
Exec=@KDE_INSTALL_FULL_LIBEXECDIR@/kpmcore_externalcommand
|
||||||
|
User=root
|
Loading…
Reference in New Issue