diff --git a/src/core/kfileitemlistproperties.cpp b/src/core/kfileitemlistproperties.cpp --- a/src/core/kfileitemlistproperties.cpp +++ b/src/core/kfileitemlistproperties.cpp @@ -37,6 +37,7 @@ m_supportsDeleting(false), m_supportsWriting(false), m_supportsMoving(false), + m_supportsPrivilegeExecution(false), m_isLocal(true) { } void setItems(const KFileItemList &items); @@ -52,6 +53,7 @@ bool m_supportsDeleting : 1; bool m_supportsWriting : 1; bool m_supportsMoving : 1; + bool m_supportsPrivilegeExecution : 1; bool m_isLocal : 1; }; @@ -90,9 +92,10 @@ bool isLocal = false; const QUrl url = item.mostLocalUrl(&isLocal); m_isLocal = m_isLocal && isLocal; + m_supportsPrivilegeExecution = KProtocolManager::supportsPrivilegeExecution(url); m_supportsReading = m_supportsReading && KProtocolManager::supportsReading(url); m_supportsDeleting = m_supportsDeleting && KProtocolManager::supportsDeleting(url); - m_supportsWriting = m_supportsWriting && KProtocolManager::supportsWriting(url) && item.isWritable(); + m_supportsWriting = m_supportsWriting && KProtocolManager::supportsWriting(url) && (m_supportsPrivilegeExecution ||item.isWritable()); m_supportsMoving = m_supportsMoving && KProtocolManager::supportsMoving(url); // For local files we can do better: check if we have write permission in parent directory @@ -103,7 +106,7 @@ if (parentDirInfo.filePath() != directory) { parentDirInfo.setFile(directory); } - if (!parentDirInfo.isWritable()) { + if (!parentDirInfo.isWritable() && !m_supportsPrivilegeExecution)) { m_supportsDeleting = false; m_supportsMoving = false; } diff --git a/src/core/kprotocolinfo.cpp b/src/core/kprotocolinfo.cpp --- a/src/core/kprotocolinfo.cpp +++ b/src/core/kprotocolinfo.cpp @@ -53,6 +53,7 @@ m_canRenameFromFile = config.readEntry("renameFromFile", false); m_canRenameToFile = config.readEntry("renameToFile", false); m_canDeleteRecursive = config.readEntry("deleteRecursive", false); + m_supportsPrivilegeExecution = config.readEntry("privilegeExecution", false); const QString fnu = config.readEntry("fileNameUsedForCopying", "FromURL"); m_fileNameUsedForCopying = KProtocolInfo::FromUrl; if (fnu == QLatin1String("Name")) { @@ -143,6 +144,7 @@ m_canRenameFromFile = json.value(QStringLiteral("renameFromFile")).toBool(); m_canRenameToFile = json.value(QStringLiteral("renameToFile")).toBool(); m_canDeleteRecursive = json.value(QStringLiteral("deleteRecursive")).toBool(); + m_supportsPrivilegeExecution = json.value(QStringLiteral("privilegeExecution")).toBool(); // default is "FromURL" const QString fnu = json.value(QStringLiteral("fileNameUsedForCopying")).toString(); diff --git a/src/core/kprotocolinfo_p.h b/src/core/kprotocolinfo_p.h --- a/src/core/kprotocolinfo_p.h +++ b/src/core/kprotocolinfo_p.h @@ -56,6 +56,7 @@ bool m_canRenameFromFile : 1; bool m_canRenameToFile : 1; bool m_canDeleteRecursive : 1; + bool m_supportsPrivilegeExecution : 1; QString m_defaultMimetype; QString m_icon; QString m_config; diff --git a/src/core/kprotocolmanager.h b/src/core/kprotocolmanager.h --- a/src/core/kprotocolmanager.h +++ b/src/core/kprotocolmanager.h @@ -640,6 +640,18 @@ * @since 4.1 */ static QString protocolForArchiveMimetype(const QString &mimeType); + + /** + * Returns whether the protocol can modify file system with elevated privileges. + * + * This corresponds to the "privilegeExecution=" field in the protocol description + * file. Valid values for this field are "true" or "false" (default). + * + * @param url the url to check + * @return true if protocol supports privilege execution + * @since 5.70 + */ + static bool supportsPrivilegeExecution(const QUrl &url); /*=============================== OTHERS ====================================*/ diff --git a/src/core/kprotocolmanager.cpp b/src/core/kprotocolmanager.cpp --- a/src/core/kprotocolmanager.cpp +++ b/src/core/kprotocolmanager.cpp @@ -1233,6 +1233,16 @@ return prot->m_supportsTruncating; } +bool KProtocolManager::supportsPrivilegeExecution(const QUrl &url) +{ + KProtocolInfoPrivate *prot = findProtocol(url); + if (!prot) { + return false; + } + + return prot->m_supportsPrivilegeExecution; +} + bool KProtocolManager::canCopyFromFile(const QUrl &url) { KProtocolInfoPrivate *prot = findProtocol(url); diff --git a/src/ioslaves/file/file.json b/src/ioslaves/file/file.json --- a/src/ioslaves/file/file.json +++ b/src/ioslaves/file/file.json @@ -29,7 +29,8 @@ "output": "filesystem", "protocol": "file", "reading": true, - "writing": true + "writing": true, + "privilegeExecution": true } } }