Index: src/core/kfileitemlistproperties.cpp =================================================================== --- src/core/kfileitemlistproperties.cpp +++ src/core/kfileitemlistproperties.cpp @@ -36,6 +36,7 @@ m_supportsDeleting(false), m_supportsWriting(false), m_supportsMoving(false), + m_supportsPrivilegeExec(false), m_isLocal(true) { } void setItems(const KFileItemList &items); @@ -51,6 +52,7 @@ bool m_supportsDeleting : 1; bool m_supportsWriting : 1; bool m_supportsMoving : 1; + bool m_supportsPrivilegeExec : 1; bool m_isLocal : 1; }; @@ -88,9 +90,10 @@ foreach (const KFileItem &item, items) { const QUrl url = item.url(); m_isLocal = m_isLocal && url.isLocalFile(); + m_supportsPrivilegeExec = 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_supportsPrivilegeExec || 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 @@ -101,7 +104,7 @@ if (parentDirInfo.filePath() != directory) { parentDirInfo.setFile(directory); } - if (!parentDirInfo.isWritable()) { + if (!parentDirInfo.isWritable() && !m_supportsPrivilegeExec) { m_supportsDeleting = false; m_supportsMoving = false; } Index: src/core/kprotocolinfo.cpp =================================================================== --- src/core/kprotocolinfo.cpp +++ src/core/kprotocolinfo.cpp @@ -27,15 +27,13 @@ #include #include #include - // // Internal functions: // KProtocolInfoPrivate::KProtocolInfoPrivate(const QString &path) { KConfig sconfig(path, KConfig::SimpleConfig); KConfigGroup config(&sconfig, "Protocol"); - m_name = config.readEntry("protocol"); m_exec = config.readPathEntry("exec", QString()); m_isSourceProtocol = config.readEntry("source", true); @@ -52,6 +50,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")) { @@ -141,6 +140,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(); Index: src/core/kprotocolinfo_p.h =================================================================== --- src/core/kprotocolinfo_p.h +++ src/core/kprotocolinfo_p.h @@ -48,6 +48,7 @@ bool m_supportsLinking : 1; bool m_supportsMoving : 1; bool m_supportsOpening : 1; + bool m_supportsPrivilegeExecution : 1; bool m_determineMimetypeFromExtension : 1; bool m_canCopyFromFile : 1; bool m_canCopyToFile : 1; Index: src/core/kprotocolmanager.h =================================================================== --- src/core/kprotocolmanager.h +++ src/core/kprotocolmanager.h @@ -468,6 +468,17 @@ static bool supportsOpening(const QUrl &url); /** + * 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 + */ + static bool supportsPrivilegeExecution(const QUrl &url); + + /** * Returns whether the protocol can copy files/objects directly from the * filesystem itself. If not, the application will read files from the * filesystem using the file-protocol and pass the data on to the destination Index: src/core/kprotocolmanager.cpp =================================================================== --- src/core/kprotocolmanager.cpp +++ src/core/kprotocolmanager.cpp @@ -1233,6 +1233,16 @@ return prot->m_supportsOpening; } +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); Index: src/ioslaves/file/file.json =================================================================== --- src/ioslaves/file/file.json +++ src/ioslaves/file/file.json @@ -28,7 +28,8 @@ "output": "filesystem", "protocol": "file", "reading": true, - "writing": true + "writing": true, + "privilegeExecution": true } } -} \ No newline at end of file +}