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 @@ -219,7 +219,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,18 @@ void infoMessage(const QString &msg); /** - * Type of message box. Should be kept in sync with KMessageBox::ButtonCode. - */ - enum MessageBoxType { QuestionYesNo = 1, WarningYesNo = 2, WarningContinueCancel = 3, WarningYesNoCancel = 4, Information = 5, SSLMessageBox = 6 }; + * 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 + WarningContinueCancelDetailed = 10, + }; /** * Button codes. Should be kept in sync with KMessageBox::ButtonCode @@ -1000,9 +1009,9 @@ * Checks with job if privilege operation is allowed. * @return privilege operation status. * @see PrivilegeOperationStatus - * @since 5.43 + * @since 5.66 */ - PrivilegeOperationStatus requestPrivilegeOperation(); + PrivilegeOperationStatus requestPrivilegeOperation(const QString &operationDetails); /** * Adds @p action to the list of PolicyKit actions which the @@ -1013,6 +1022,14 @@ */ void addTemporaryAuthorization(const QString &action); + /** + * @deprecated since 5.66, use requestPrivilegeOperation(QString) + */ + +#if KIOCORE_ENABLE_DEPRECATED_SINCE(5, 66) + KIOCORE_DEPRECATED_VERSION(5, 66, "Pass QString action to requestPrivilegeOperation") 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 @@ -141,19 +141,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 @@ -1535,8 +1522,9 @@ return result; } -PrivilegeOperationStatus SlaveBase::requestPrivilegeOperation() +PrivilegeOperationStatus SlaveBase::requestPrivilegeOperation(const QString &operationDetails) { + if (d->m_privilegeOperationStatus == OperationNotAllowed) { QByteArray buffer; send(MSG_PRIVILEGE_EXEC); @@ -1548,7 +1536,13 @@ if (metaData(QStringLiteral("UnitTesting")) != QLatin1String("true") && d->m_privilegeOperationStatus == OperationAllowed && !d->m_confirmationAsked) { - d->m_privilegeOperationStatus = d->askConfirmation(); + //KF6 TODO Remove. We don't want to pass details as meta-data. Pass it as a parameter in messageBox(). + 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; } @@ -1559,3 +1553,10 @@ { d->m_tempAuths.insert(action); } + +#if KIOCORE_BUILD_DEPRECATED_SINCE(5, 66) +PrivilegeOperationStatus SlaveBase::requestPrivilegeOperation() +{ + return KIO::OperationNotAllowed; +} +#endif diff --git a/src/core/slaveinterface.cpp b/src/core/slaveinterface.cpp --- a/src/core/slaveinterface.cpp +++ b/src/core/slaveinterface.cpp @@ -288,6 +288,8 @@ break; } } + } else if (m.contains(QStringLiteral("privilege_conf_details"))) { // KF6 TODO Remove this conditional. + d->privilegeConfMetaData = m; } emit metaData(m); break; @@ -421,6 +423,8 @@ if (type == KIO::SlaveBase::SSLMessageBox) { data.insert(UserNotificationHandler::MSG_META_DATA, d->sslMetaData.toVariant()); + } else if (type == KIO::SlaveBase::WarningContinueCancelDetailed) { // KF6 TODO Remove + 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,10 @@ // We need some metadata here for our SSL code in messageBox() and for sslMetaData(). MetaData sslMetaData; + // Since 5.66 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, KRandom::randomString(6)).arg(getpid()); } +static QString actionDetails(ActionType actionType, const 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")) @@ -879,7 +929,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,20 +139,21 @@ * @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.66 this is also used for privilege operation details. * * @since 4.11 * * @internal */ + // KF6 TODO Add a QString parameter for "details" and keep in sync with API in SlaveBase, SlaveInterface, and JobUiDelegateExtension. int requestMessageBox(MessageBoxType type, const QString &text, const QString &caption, const QString &buttonYes, const QString &buttonNo, 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; /** * 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 @@ -300,7 +300,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; @@ -342,7 +342,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(QLatin1Char('\x01'), QString::SkipEmptyParts); + const QStringList sl = metaData.value(QStringLiteral("ssl_peer_chain")).split(QLatin1Char('\x01'), QString::SkipEmptyParts); QList certChain; bool decodedOk = true; for (const QString &s : sl) { @@ -356,13 +356,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::certificateErrorsFromString(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::certificateErrorsFromString(metaData.value(QStringLiteral("ssl_cert_errors")))); kid->exec(); } else { result = -1; @@ -374,6 +374,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, options | KMessageBox::Dangerous, details); + break; + } default: qCWarning(KIO_WIDGETS) << "Unknown type" << type; result = 0;