diff --git a/src/buffer/katesecuretextbuffer.cpp b/src/buffer/katesecuretextbuffer.cpp --- a/src/buffer/katesecuretextbuffer.cpp +++ b/src/buffer/katesecuretextbuffer.cpp @@ -50,6 +50,26 @@ return ActionReply::HelperErrorReply(); } +ActionReply SecureTextBuffer::openfileforwrite(const QVariantMap &args) +{ + if (!UnixFileDescriptor::isSupported()) { + return ActionReply::HelperErrorReply(); + } + + const QString file = args[QStringLiteral("file")].toString(); + QFile saveFile(file); + if (!saveFile.open(QIODevice::WriteOnly)) { + return ActionReply::HelperErrorReply(); + } + + ActionReply reply; + QVariantMap data; + auto variantFd = QVariant::fromValue(UnixFileDescriptor(saveFile.handle())); + data.insert(QStringLiteral("fd"), variantFd); + reply.setData(data); + return reply; +} + bool SecureTextBuffer::saveFileInternal(const QString &sourceFile, const QString &targetFile, const QByteArray &checksum, const uint ownerId, const uint groupId) { diff --git a/src/buffer/katesecuretextbuffer_p.h b/src/buffer/katesecuretextbuffer_p.h --- a/src/buffer/katesecuretextbuffer_p.h +++ b/src/buffer/katesecuretextbuffer_p.h @@ -71,6 +71,8 @@ */ static ActionReply savefile(const QVariantMap &args); + static ActionReply openfileforwrite(const QVariantMap &args); + }; #endif diff --git a/src/buffer/katetextbuffer.cpp b/src/buffer/katetextbuffer.cpp --- a/src/buffer/katetextbuffer.cpp +++ b/src/buffer/katetextbuffer.cpp @@ -910,34 +910,62 @@ uint groupId = -2; QScopedPointer temporaryBuffer; - /** - * Memorize owner and group. - */ - const QFileInfo fileInfo(filename); - if (fileInfo.exists()) { - ownerId = fileInfo.ownerId(); - groupId = fileInfo.groupId(); - } + QScopedPointer fileForWrite; + UnixFileDescriptor dbusFd; + if (UnixFileDescriptor::isSupported()) { + KAuth::Action kAuthSaveAction(QStringLiteral("org.kde.ktexteditor.katetextbuffer.openfileforwrite")); + kAuthSaveAction.setHelperId(QStringLiteral("org.kde.ktexteditor.katetextbuffer")); + kAuthSaveAction.addArgument(QStringLiteral("file"), filename); + KAuth::ExecuteJob *job = kAuthSaveAction.execute(); + if (!job->exec()) { + return false; + } + dbusFd = job->data().value(QStringLiteral("fd")).value(); + if (!dbusFd.isValid()) { + return false; + } + fileForWrite.reset(new QFile); + if (!fileForWrite->open(dbusFd.fileDescriptor(), QIODevice::WriteOnly)) { + return false; + } + saveFile.reset(new KCompressionDevice(fileForWrite.data(), false, type)); + if (!saveFile->open(QIODevice::WriteOnly)) { + return false; + } + } else { + /** + * Memorize owner and group. + */ + const QFileInfo fileInfo(filename); + if (fileInfo.exists()) { + ownerId = fileInfo.ownerId(); + groupId = fileInfo.groupId(); + } - // if that fails we need more privileges to save this file - // -> we write to a temporary file and then send its path to KAuth action for privileged save - temporaryBuffer.reset(new QBuffer()); + // if that fails we need more privileges to save this file + // -> we write to a temporary file and then send its path to KAuth action for privileged save + temporaryBuffer.reset(new QBuffer()); - // open buffer for write and read (read is used for checksum computing and writing to temporary file) - if (!temporaryBuffer->open(QIODevice::ReadWrite)) { - return false; - } + // open buffer for write and read (read is used for checksum computing and writing to temporary file) + if (!temporaryBuffer->open(QIODevice::ReadWrite)) { + return false; + } - // we are now saving to a temporary buffer with potential compression proxy - saveFile.reset(new KCompressionDevice(temporaryBuffer.data(), false, type)); - if (!saveFile->open(QIODevice::WriteOnly)) { - return false; + // we are now saving to a temporary buffer with potential compression proxy + saveFile.reset(new KCompressionDevice(temporaryBuffer.data(), false, type)); + if (!saveFile->open(QIODevice::WriteOnly)) { + return false; + } } if( !saveBuffer(filename, *saveFile) ) { return false; } + if ( fileForWrite) { + return true; + } + // temporary buffer was used to save the file // -> computing checksum // -> saving to temporary file diff --git a/src/buffer/org.kde.ktexteditor.katetextbuffer.actions b/src/buffer/org.kde.ktexteditor.katetextbuffer.actions --- a/src/buffer/org.kde.ktexteditor.katetextbuffer.actions +++ b/src/buffer/org.kde.ktexteditor.katetextbuffer.actions @@ -122,3 +122,10 @@ Policy=auth_admin # No persistence #Persistence= + +[org.kde.ktexteditor.katetextbuffer.openfileforwrite] +Name=Open File for Write +Description=Root privileges are needed to open this file for write +Policy=auth_admin +# No persistence +#Persistence=