Changeset View
Changeset View
Standalone View
Standalone View
src/util/externalcommand.cpp
Show All 19 Lines | |||||
20 | #include "core/device.h" | 20 | #include "core/device.h" | ||
21 | #include "core/copysource.h" | 21 | #include "core/copysource.h" | ||
22 | #include "core/copytarget.h" | 22 | #include "core/copytarget.h" | ||
23 | #include "core/copytargetbytearray.h" | 23 | #include "core/copytargetbytearray.h" | ||
24 | #include "core/copysourcedevice.h" | 24 | #include "core/copysourcedevice.h" | ||
25 | #include "core/copytargetdevice.h" | 25 | #include "core/copytargetdevice.h" | ||
26 | #include "util/globallog.h" | 26 | #include "util/globallog.h" | ||
27 | #include "util/externalcommand.h" | 27 | #include "util/externalcommand.h" | ||
28 | #include "util/externalcommand_polkitbackend.h" | ||||
29 | #include "util/externalcommandhelper.h" | ||||
28 | #include "util/report.h" | 30 | #include "util/report.h" | ||
29 | | ||||
30 | #include "externalcommandhelper_interface.h" | 31 | #include "externalcommandhelper_interface.h" | ||
31 | 32 | | |||
32 | #include <QCryptographicHash> | 33 | #include <QtDBus> | ||
33 | #include <QDBusConnection> | | |||
34 | #include <QDBusInterface> | | |||
35 | #include <QDBusReply> | | |||
36 | #include <QEventLoop> | 34 | #include <QEventLoop> | ||
37 | #include <QtGlobal> | | |||
38 | #include <QStandardPaths> | 35 | #include <QStandardPaths> | ||
39 | #include <QString> | 36 | #include <QString> | ||
40 | #include <QStringList> | 37 | #include <QStringList> | ||
41 | #include <QTimer> | | |||
42 | #include <QThread> | 38 | #include <QThread> | ||
39 | #include <QTimer> | ||||
43 | #include <QVariant> | 40 | #include <QVariant> | ||
44 | 41 | | |||
45 | #include <KAuth> | | |||
46 | #include <KJob> | 42 | #include <KJob> | ||
47 | #include <KLocalizedString> | 43 | #include <KLocalizedString> | ||
48 | 44 | | |||
45 | #include <PolkitQt1/Authority> | ||||
46 | | ||||
49 | struct ExternalCommandPrivate | 47 | struct ExternalCommandPrivate | ||
50 | { | 48 | { | ||
51 | Report *m_Report; | 49 | Report *m_Report; | ||
52 | QString m_Command; | 50 | QString m_Command; | ||
53 | QStringList m_Args; | 51 | QStringList m_Args; | ||
54 | int m_ExitCode; | 52 | int m_ExitCode; | ||
55 | QByteArray m_Output; | 53 | QByteArray m_Output; | ||
56 | QByteArray m_Input; | 54 | QByteArray m_Input; | ||
57 | DBusThread *m_thread; | 55 | DBusThread *m_thread; | ||
58 | QProcess::ProcessChannelMode processChannelMode; | 56 | QProcess::ProcessChannelMode processChannelMode; | ||
59 | }; | 57 | }; | ||
60 | 58 | | |||
61 | KAuth::ExecuteJob* ExternalCommand::m_job; | | |||
62 | bool ExternalCommand::helperStarted = false; | 59 | bool ExternalCommand::helperStarted = false; | ||
63 | QWidget* ExternalCommand::parent; | 60 | QWidget* ExternalCommand::parent; | ||
64 | 61 | Auth::PolkitQt1Backend* ExternalCommand::m_authJob; | |||
65 | 62 | | |||
66 | /** Creates a new ExternalCommand instance without Report. | 63 | /** Creates a new ExternalCommand instance without Report. | ||
67 | @param cmd the command to run | 64 | @param cmd the command to run | ||
68 | @param args the arguments to pass to the command | 65 | @param args the arguments to pass to the command | ||
69 | */ | 66 | */ | ||
70 | ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) : | 67 | ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, const QProcess::ProcessChannelMode processChannelMode) : | ||
71 | d(std::make_unique<ExternalCommandPrivate>()) | 68 | d(std::make_unique<ExternalCommandPrivate>()) | ||
72 | { | 69 | { | ||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Line(s) | 118 | { | |||
133 | 130 | | |||
134 | if ( qEnvironmentVariableIsSet( "KPMCORE_DEBUG" )) | 131 | if ( qEnvironmentVariableIsSet( "KPMCORE_DEBUG" )) | ||
135 | qDebug() << xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" "))); | 132 | qDebug() << xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" "))); | ||
136 | 133 | | |||
137 | QString cmd = QStandardPaths::findExecutable(command()); | 134 | QString cmd = QStandardPaths::findExecutable(command()); | ||
138 | if (cmd.isEmpty()) | 135 | if (cmd.isEmpty()) | ||
139 | cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); | 136 | cmd = QStandardPaths::findExecutable(command(), { QStringLiteral("/sbin/"), QStringLiteral("/usr/sbin/"), QStringLiteral("/usr/local/sbin/") }); | ||
140 | 137 | | |||
141 | auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | 138 | auto interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | ||
142 | QStringLiteral("/Helper"), QDBusConnection::systemBus(), this); | 139 | QStringLiteral("/Helper"), QDBusConnection::systemBus(), this); | ||
143 | 140 | | |||
144 | interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days | 141 | interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days | ||
145 | 142 | | |||
146 | bool rval = false; | 143 | bool rval = false; | ||
147 | 144 | | |||
148 | QDBusPendingCall pcall = interface->start(cmd, args(), d->m_Input, d->processChannelMode); | 145 | QDBusPendingCall pcall = interface->start(cmd, args(), d->m_Input, d->processChannelMode); | ||
149 | 146 | | |||
Show All 27 Lines | 173 | { | |||
177 | bool rval = true; | 174 | bool rval = true; | ||
178 | const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy | 175 | const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy | ||
179 | 176 | | |||
180 | if (!QDBusConnection::systemBus().isConnected()) { | 177 | if (!QDBusConnection::systemBus().isConnected()) { | ||
181 | qWarning() << QDBusConnection::systemBus().lastError().message(); | 178 | qWarning() << QDBusConnection::systemBus().lastError().message(); | ||
182 | return false; | 179 | return false; | ||
183 | } | 180 | } | ||
184 | 181 | | |||
185 | // TODO KF6:Use new signal-slot syntax | 182 | /*Use signals from externalcommandhelper*/ | ||
186 | connect(m_job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long))); | 183 | //connect(m_authJob, &ExternalCommandHelper::reportProgress, this, &ExternalCommand::emitReport); | ||
shubham: these connect gives error and correctly so because of m_authJob. Any suggestion how to tackle? | |||||
Well, report progress used KAuth, Now progress will have to be sent via DBus message. So ExternalCommandHelper class will act as DBus client and send messages to ExternalCommand class. Comment it out for now. It will obviously make kpmcore not fully functional until it is reimplemnted, but I think it might still work (just no progress reporting). stikonas: Well, report progress used KAuth, Now progress will have to be sent via DBus message. So… | |||||
progress() and reportProgress() signals have been reimplemented in the qdbus patch. We are now NOT using KAuth's HelperSupport::reportProgress() function which internally used to emit the signal. shubham: progress() and reportProgress() signals have been reimplemented in the qdbus patch. We are now… | |||||
187 | connect(m_job, &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport); | 184 | //connect(m_authJob, &ExternalCommandHelper::progress, this, &ExternalCommand::emitProgress); | ||
188 | 185 | | |||
189 | auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | 186 | auto interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | ||
190 | QStringLiteral("/Helper"), QDBusConnection::systemBus(), this); | 187 | QStringLiteral("/Helper"), QDBusConnection::systemBus(), this); | ||
191 | interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days | 188 | interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days | ||
192 | 189 | | |||
193 | QDBusPendingCall pcall = interface->copyblocks(source.path(), source.firstByte(), source.length(), | 190 | QDBusPendingCall pcall = interface->copyblocks(source.path(), source.firstByte(), source.length(), | ||
194 | target.path(), target.firstByte(), blockSize); | 191 | target.path(), target.firstByte(), blockSize); | ||
195 | 192 | | |||
196 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); | 193 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); | ||
197 | QEventLoop loop; | 194 | QEventLoop loop; | ||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Line(s) | 265 | /** Runs the command. | |||
269 | @param timeout timeout to use for waiting when starting and when waiting for the process to finish | 266 | @param timeout timeout to use for waiting when starting and when waiting for the process to finish | ||
270 | @return true on success | 267 | @return true on success | ||
271 | */ | 268 | */ | ||
272 | bool ExternalCommand::run(int timeout) | 269 | bool ExternalCommand::run(int timeout) | ||
273 | { | 270 | { | ||
274 | return start(timeout) /* && exitStatus() == 0*/; | 271 | return start(timeout) /* && exitStatus() == 0*/; | ||
275 | } | 272 | } | ||
276 | 273 | | |||
277 | void ExternalCommand::onReadOutput() | 274 | //void ExternalCommand::onReadOutput() | ||
278 | { | 275 | //{ | ||
279 | // const QByteArray s = readAllStandardOutput(); | 276 | // const QByteArray s = readAllStandardOutput(); | ||
280 | // | 277 | // | ||
281 | // if(m_Output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems | 278 | // if(m_Output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems | ||
282 | // if (report()) | 279 | // if (report()) | ||
283 | // report()->line() << xi18nc("@info:status", "(Command is printing too much output)"); | 280 | // report()->line() << xi18nc("@info:status", "(Command is printing too much output)"); | ||
284 | // return; | 281 | // return; | ||
285 | // } | 282 | // } | ||
286 | // | 283 | // | ||
287 | // m_Output += s; | 284 | // m_Output += s; | ||
288 | // | 285 | // | ||
289 | // if (report()) | 286 | // if (report()) | ||
290 | // *report() << QString::fromLocal8Bit(s); | 287 | // *report() << QString::fromLocal8Bit(s); | ||
291 | } | 288 | //} | ||
292 | 289 | | |||
293 | void ExternalCommand::setCommand(const QString& cmd) | 290 | void ExternalCommand::setCommand(const QString& cmd) | ||
294 | { | 291 | { | ||
295 | d->m_Command = cmd; | 292 | d->m_Command = cmd; | ||
296 | } | 293 | } | ||
297 | 294 | | |||
298 | const QString& ExternalCommand::command() const | 295 | const QString& ExternalCommand::command() const | ||
299 | { | 296 | { | ||
Show All 35 Lines | 331 | { | |||
335 | return d->m_Report; | 332 | return d->m_Report; | ||
336 | } | 333 | } | ||
337 | 334 | | |||
338 | void ExternalCommand::setExitCode(int i) | 335 | void ExternalCommand::setExitCode(int i) | ||
339 | { | 336 | { | ||
340 | d->m_ExitCode = i; | 337 | d->m_ExitCode = i; | ||
341 | } | 338 | } | ||
342 | 339 | | |||
343 | /**< Dummy function for QTimer when needed. */ | 340 | // Dummy function for QTimer | ||
344 | void ExternalCommand::quit() | 341 | void ExternalCommand::quit() | ||
345 | { | 342 | { | ||
346 | 343 | | |||
347 | } | 344 | } | ||
348 | 345 | | |||
349 | bool ExternalCommand::startHelper() | 346 | bool ExternalCommand::startHelper() | ||
350 | { | 347 | { | ||
351 | if (!QDBusConnection::systemBus().isConnected()) { | 348 | if (!QDBusConnection::systemBus().isConnected()) { | ||
352 | qWarning() << QDBusConnection::systemBus().lastError().message(); | 349 | qWarning() << QDBusConnection::systemBus().lastError().message(); | ||
353 | return false; | 350 | return false; | ||
354 | } | 351 | } | ||
355 | 352 | | |||
356 | QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); | 353 | QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); | ||
354 | | ||||
357 | if (iface.isValid()) { | 355 | if (iface.isValid()) { | ||
358 | exit(0); | 356 | exit(0); | ||
359 | } | 357 | } | ||
360 | 358 | | |||
361 | d->m_thread = new DBusThread; | 359 | d->m_thread = new DBusThread; | ||
362 | d->m_thread->start(); | 360 | d->m_thread->start(); | ||
363 | 361 | | |||
364 | KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init")); | 362 | ////////////////////////////////////// | ||
365 | action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); | 363 | // Authorize using Polkit backend /// | ||
366 | action.setTimeout(10 * 24 * 3600 * 1000); // 10 days | 364 | //////////////////////////////////// | ||
367 | action.setParentWidget(parent); | 365 | | ||
368 | QVariantMap arguments; | 366 | // initialize KDE Polkit daemon | ||
369 | action.setArguments(arguments); | 367 | m_authJob->initPolkitAgent(QStringLiteral("org.kde.kpmcore.externalcommand.init"), parent); | ||
370 | m_job = action.execute(); | | |||
371 | m_job->start(); | | |||
372 | 368 | | |||
373 | // Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop) | 369 | bool isActionAuthorized = m_authJob->authorizeAction(QStringLiteral("org.kde.kpmcore.externalcommand.init"), m_authJob->callerID()); | ||
370 | | ||||
371 | auto authResult = m_authJob->actionStatus(QStringLiteral("org.kde.kpmcore.externalcommand.init"), m_authJob->callerID()); | ||||
372 | | ||||
373 | | ||||
374 | // Wait until ExternalCommand Helper is ready (helper sends progress(int) and reportProgress(QVariantMap &) signal just before it enters event loop) | ||||
374 | QEventLoop loop; | 375 | QEventLoop loop; | ||
375 | auto exitLoop = [&] () { loop.exit(); }; | 376 | auto exitLoop = [&] () { loop.exit(); }; | ||
376 | auto conn = QObject::connect(m_job, &KAuth::ExecuteJob::newData, exitLoop); | 377 | //auto conn1 = QObject::connect(m_authJob, &ExternalCommandHelper::progress, exitLoop); | ||
377 | QObject::connect(m_job, &KJob::finished, [=] () { if(m_job->error()) exitLoop(); } ); | 378 | //auto conn2 = QObject::connect(m_authJob, &ExternalCommandHelper::reportProgress, exitLoop); | ||
379 | | ||||
380 | //QObject::connect(m_job, &KJob::finished, [=] () { if(m_job->error()) exitLoop(); } ); | ||||
381 | | ||||
378 | loop.exec(); | 382 | loop.exec(); | ||
379 | QObject::disconnect(conn); | 383 | | ||
384 | //QObject::disconnect(conn1); | ||||
385 | //QObject::disconnect(conn2); | ||||
386 | | ||||
stikonas: spelling, `executeAction()` | |||||
387 | if (!isActionAuthorized || authResult == PolkitQt1::Authority::No) { | ||||
388 | qDebug() << "Unable to obtain Administrative privileges, the action can not be executed!!"; | ||||
389 | } | ||||
380 | 390 | | |||
381 | helperStarted = true; | 391 | helperStarted = true; | ||
382 | return true; | 392 | return true; | ||
383 | } | 393 | } | ||
384 | 394 | | |||
385 | void ExternalCommand::stopHelper() | 395 | void ExternalCommand::stopHelper() | ||
386 | { | 396 | { | ||
387 | auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | 397 | auto interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | ||
388 | QStringLiteral("/Helper"), QDBusConnection::systemBus()); | 398 | QStringLiteral("/Helper"), QDBusConnection::systemBus()); | ||
389 | interface->exit(); | 399 | interface->exit(); | ||
390 | | ||||
391 | } | 400 | } | ||
392 | 401 | | |||
393 | void DBusThread::run() | 402 | void DBusThread::run() | ||
394 | { | 403 | { | ||
395 | if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface")) || | 404 | if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface")) || | ||
396 | !QDBusConnection::systemBus().registerObject(QStringLiteral("/Application"), this, QDBusConnection::ExportAllSlots)) { | 405 | !QDBusConnection::systemBus().registerObject(QStringLiteral("/Application"), this, QDBusConnection::ExportAllSlots)) { | ||
397 | qWarning() << QDBusConnection::systemBus().lastError().message(); | 406 | qWarning() << QDBusConnection::systemBus().lastError().message(); | ||
398 | return; | 407 | return; | ||
399 | } | 408 | } | ||
400 | 409 | | |||
401 | QEventLoop loop; | 410 | QEventLoop loop; | ||
402 | loop.exec(); | 411 | loop.exec(); | ||
403 | } | 412 | } | ||
413 | | ||||
414 | #include "moc_externalcommand.cpp" |
these connect gives error and correctly so because of m_authJob. Any suggestion how to tackle? Ditto at line 377