diff --git a/autotests/kiotesthelper.h b/autotests/kiotesthelper.h --- a/autotests/kiotesthelper.h +++ b/autotests/kiotesthelper.h @@ -178,16 +178,16 @@ const QString &iconYes = QString(), const QString &iconNo = QString(), const QString &dontAskAgainName = QString(), - const KIO::MetaData &sslMetaData = KIO::MetaData()) override { + const KIO::MetaData &metaData = KIO::MetaData()) override { Q_UNUSED(type); Q_UNUSED(text); Q_UNUSED(caption); Q_UNUSED(buttonYes); Q_UNUSED(buttonNo); Q_UNUSED(iconYes); Q_UNUSED(iconNo); Q_UNUSED(dontAskAgainName); - Q_UNUSED(sslMetaData); + Q_UNUSED(metaData); ++m_messageBoxCalled; return m_messageBoxResult; } diff --git a/src/core/jobuidelegateextension.h b/src/core/jobuidelegateextension.h --- a/src/core/jobuidelegateextension.h +++ b/src/core/jobuidelegateextension.h @@ -227,7 +227,9 @@ WarningContinueCancel = 3, WarningYesNoCancel = 4, Information = 5, - SSLMessageBox = 6 + SSLMessageBox = 6, + //In KMessageBox::DialogType; Sorry = 7, Error = 8, QuestionYesNoCancel = 9 + WarningContinueCancelDetailed = 10, }; /** diff --git a/src/core/slavebase.h b/src/core/slavebase.h --- a/src/core/slavebase.h +++ b/src/core/slavebase.h @@ -257,9 +257,10 @@ void infoMessage(const QString &msg); /** - * Type of message box. Should be kept in sync with KMessageBox::ButtonCode. + * Type of message box. Should be kept in sync with KMessageBox::DialogType. */ - enum MessageBoxType { QuestionYesNo = 1, WarningYesNo = 2, WarningContinueCancel = 3, WarningYesNoCancel = 4, Information = 5, SSLMessageBox = 6 }; + //In KMessageBox::DialogType; Sorry = 7, Error = 8, QuestionYesNoCancel = 9 + enum MessageBoxType { QuestionYesNo = 1, WarningYesNo = 2, WarningContinueCancel = 3, WarningYesNoCancel = 4, Information = 5, SSLMessageBox = 6, WarningContinueCancelDetailed = 10, }; /** * Button codes. Should be kept in sync with KMessageBox::ButtonCode @@ -939,9 +940,9 @@ * Checks with job if privilege operation is allowed. * @return privilege operation status. * @see PrivilegeOperationStatus - * @since 5.43 + * @since 5.65 */ - PrivilegeOperationStatus requestPrivilegeOperation(); + PrivilegeOperationStatus requestPrivilegeOperation(const QString &operationDetails); /** * Adds @p action to the list of PolicyKit actions which the @@ -952,6 +953,14 @@ */ void addTemporaryAuthorization(const QString &action); + /** + * @deprecated since 5.65, use requestPrivilegeOperation(QString) + */ + +#ifndef KIOCORE_NO_DEPRECATED + KIOCORE_DEPRECATED PrivilegeOperationStatus requestPrivilegeOperation(); +#endif + protected: /** * Name of the protocol supported by this slave diff --git a/src/core/slavebase.cpp b/src/core/slavebase.cpp --- a/src/core/slavebase.cpp +++ b/src/core/slavebase.cpp @@ -132,19 +132,6 @@ QString m_warningMessage; int m_privilegeOperationStatus; - PrivilegeOperationStatus askConfirmation() - { - int status = q->messageBox(SlaveBase::WarningContinueCancel, m_warningMessage, m_warningCaption, QStringLiteral("Continue"), QStringLiteral("Cancel")); - switch (status) { - case SlaveBase::Continue: - return OperationAllowed; - case SlaveBase::Cancel: - return OperationCanceled; - default: - return OperationNotAllowed; - } - } - void updateTempAuthStatus() { #ifdef Q_OS_UNIX @@ -1505,8 +1492,9 @@ return result; } -PrivilegeOperationStatus SlaveBase::requestPrivilegeOperation() +PrivilegeOperationStatus SlaveBase::requestPrivilegeOperation(const QString &operationDetails) { + if (d->m_privilegeOperationStatus == OperationNotAllowed) { QByteArray buffer; send(MSG_PRIVILEGE_EXEC); @@ -1518,7 +1506,11 @@ if (metaData(QStringLiteral("UnitTesting")) != QLatin1String("true") && d->m_privilegeOperationStatus == OperationAllowed && !d->m_confirmationAsked) { - d->m_privilegeOperationStatus = d->askConfirmation(); + setMetaData(QStringLiteral("privilege_conf_details"), operationDetails); + sendMetaData(); + int result = messageBox(d->m_warningMessage, WarningContinueCancelDetailed, + d->m_warningCaption, QString(), QString(), QString()); + d->m_privilegeOperationStatus = result == Continue ? OperationAllowed : OperationCanceled; d->m_confirmationAsked = true; } @@ -1529,3 +1521,10 @@ { d->m_tempAuths.insert(action); } + +#ifndef KIOCORE_NO_DEPRECATED +PrivilegeOperationStatus SlaveBase::requestPrivilegeOperation() +{ + return KIO::OperationNotAllowed; +} +#endif diff --git a/src/core/slaveinterface.h b/src/core/slaveinterface.h --- a/src/core/slaveinterface.h +++ b/src/core/slaveinterface.h @@ -86,7 +86,7 @@ MSG_WRITTEN, MSG_HOST_INFO_REQ, MSG_PRIVILEGE_EXEC, - MSG_SLAVE_STATUS_V2 + MSG_SLAVE_STATUS_V2, // add new ones here once a release is done, to avoid breaking binary compatibility }; diff --git a/src/core/slaveinterface.cpp b/src/core/slaveinterface.cpp --- a/src/core/slaveinterface.cpp +++ b/src/core/slaveinterface.cpp @@ -292,6 +292,8 @@ break; } } + } else if (m.contains("privilege_conf_details")) { + d->privilegeConfMetaData = m; } emit metaData(m); break; @@ -425,6 +427,8 @@ if (type == KIO::SlaveBase::SSLMessageBox) { data.insert(UserNotificationHandler::MSG_META_DATA, d->sslMetaData.toVariant()); + } else if (type == KIO::SlaveBase::WarningContinueCancelDetailed) { + data.insert(UserNotificationHandler::MSG_META_DATA, d->privilegeConfMetaData.toVariant()); } globalUserNotificationHandler()->requestMessageBox(this, type, data); diff --git a/src/core/slaveinterface_p.h b/src/core/slaveinterface_p.h --- a/src/core/slaveinterface_p.h +++ b/src/core/slaveinterface_p.h @@ -52,6 +52,9 @@ // We need some metadata here for our SSL code in messageBox() and for sslMetaData(). MetaData sslMetaData; + // Since 5.65 this is used for sending privilege operation details. + // KF6 TODO remove this hack. + MetaData privilegeConfMetaData; KIO::filesize_t sizes[max_nums]; qint64 times[max_nums]; diff --git a/src/ioslaves/file/file_unix.cpp b/src/ioslaves/file/file_unix.cpp --- a/src/ioslaves/file/file_unix.cpp +++ b/src/ioslaves/file/file_unix.cpp @@ -78,6 +78,56 @@ return QStringLiteral("%1/filehelper%2%3").arg(runtimeDir).arg(KRandom::randomString(6)).arg(getpid()); } +static QString actionDetails(ActionType actionType, QVariantList args) +{ + QString action, detail; + switch(actionType) { + case CHMOD: + action = i18n("Change File Permissions"); + detail = i18n("New Permissions : %1", args[1].toInt()); + break; + case CHOWN: + action = i18n("Change File Owner"); + detail = i18n("New Owner : UID=%1, GID=%2", args[1].toInt(), args[2].toInt()); + break; + case DEL: + action = i18n("Remove File"); + break; + case RMDIR: + action = i18n("Remove Directory"); + break; + case MKDIR: + action = i18n("Create Directory"); + detail = i18n("Directory Permissions: %1", args[1].toInt()); + break; + case OPEN: + action = i18n("Open File"); + break; + case OPENDIR: + action = i18n("Open Directory"); + break; + case RENAME: + action = i18n("Rename"); + detail = i18n("New Filename: %1", args[1].toString()); + break; + case SYMLINK: + action = i18n("Create Symlink"); + detail = i18n("Target: %1", args[1].toString()); + break; + case UTIME: + action = i18n("Change Timestamp"); + break; + default: + action = i18n("Unknown Action"); + break; + } + + const QString metadata = i18n("Action: %1\n" + "Source: %2\n" + "%3", action, args[0].toString(), detail); + return metadata; +} + bool FileProtocol::privilegeOperationUnitTestMode() { return (metaData(QStringLiteral("UnitTesting")) == QLatin1String("true")) @@ -842,7 +892,8 @@ return PrivilegeOperationReturnValue::failure(errcode); } - KIO::PrivilegeOperationStatus opStatus = requestPrivilegeOperation(); + const QString operationDetails = actionDetails(action, args); + KIO::PrivilegeOperationStatus opStatus = requestPrivilegeOperation(operationDetails); if (opStatus != KIO::OperationAllowed) { if (opStatus == KIO::OperationCanceled) { error(KIO::ERR_USER_CANCELED, QString()); diff --git a/src/widgets/jobuidelegate.h b/src/widgets/jobuidelegate.h --- a/src/widgets/jobuidelegate.h +++ b/src/widgets/jobuidelegate.h @@ -139,7 +139,7 @@ * @param iconYes the icon shown on the YES button. * @param iconNo the icon shown on the NO button. * @param dontAskAgainName the name used to store result from 'Do not ask again' checkbox. - * @param sslMetaData SSL information used by the SSLMessageBox. + * @param metaData SSL information used by the SSLMessageBox. Since 5.65 this is also used for privilege operation details. * * @since 4.11 * @@ -152,7 +152,7 @@ const QString &iconYes = QString(), const QString &iconNo = QString(), const QString &dontAskAgainName = QString(), - const KIO::MetaData &sslMetaData = KIO::MetaData()) override; + const KIO::MetaData &metaData = KIO::MetaData()) override; // KF6 TODO Add proper API /** * Creates a clipboard updater diff --git a/src/widgets/jobuidelegate.cpp b/src/widgets/jobuidelegate.cpp --- a/src/widgets/jobuidelegate.cpp +++ b/src/widgets/jobuidelegate.cpp @@ -296,7 +296,7 @@ const QString &buttonYes, const QString &buttonNo, const QString &iconYes, const QString &iconNo, const QString &dontAskAgainName, - const KIO::MetaData &sslMetaData) + const KIO::MetaData &metaData) { int result = -1; @@ -338,7 +338,7 @@ case SSLMessageBox: { QPointer kid(new KSslInfoDialog(window())); //### this is boilerplate code and appears in khtml_part.cpp almost unchanged! - const QStringList sl = sslMetaData.value(QStringLiteral("ssl_peer_chain")).split('\x01', QString::SkipEmptyParts); + const QStringList sl = metaData.value(QStringLiteral("ssl_peer_chain")).split('\x01', QString::SkipEmptyParts); QList certChain; bool decodedOk = true; foreach (const QString &s, sl) { @@ -352,13 +352,13 @@ if (decodedOk) { result = 1; // whatever kid->setSslInfo(certChain, - sslMetaData.value(QStringLiteral("ssl_peer_ip")), + metaData.value(QStringLiteral("ssl_peer_ip")), text, // the URL - sslMetaData.value(QStringLiteral("ssl_protocol_version")), - sslMetaData.value(QStringLiteral("ssl_cipher")), - sslMetaData.value(QStringLiteral("ssl_cipher_used_bits")).toInt(), - sslMetaData.value(QStringLiteral("ssl_cipher_bits")).toInt(), - KSslInfoDialog::errorsFromString(sslMetaData.value(QStringLiteral("ssl_cert_errors")))); + metaData.value(QStringLiteral("ssl_protocol_version")), + metaData.value(QStringLiteral("ssl_cipher")), + metaData.value(QStringLiteral("ssl_cipher_used_bits")).toInt(), + metaData.value(QStringLiteral("ssl_cipher_bits")).toInt(), + KSslInfoDialog::errorsFromString(metaData.value(QStringLiteral("ssl_cert_errors")))); kid->exec(); } else { result = -1; @@ -370,6 +370,13 @@ delete kid; break; } + case WarningContinueCancelDetailed: { + const QString details = metaData.value(QStringLiteral("privilege_conf_details")); + result = KMessageBox::warningContinueCancelDetailed( + window(), text, caption, KStandardGuiItem::cont(), KStandardGuiItem::cancel(), dontAskAgainName, + KMessageBox::Options(KMessageBox::Dangerous | KMessageBox::WindowModal), details); + break; + } default: qCWarning(KIO_WIDGETS) << "Unknown type" << type; result = 0;