diff --git a/src/buffer/katetextbuffer.cpp b/src/buffer/katetextbuffer.cpp --- a/src/buffer/katetextbuffer.cpp +++ b/src/buffer/katetextbuffer.cpp @@ -34,7 +34,7 @@ #include #endif -#include +#include #include #include #include @@ -766,33 +766,29 @@ // codec must be set! Q_ASSERT(m_textCodec); - const bool newFile = !QFile::exists(filename); - /** - * Memorize owner and group. Due to design of QSaveFile we will have to re-set them after save is complete. + * use QFile for file saving in the normal case */ - uint ownerId = -2; - uint groupId = -2; - if (!newFile) { - QFileInfo fileInfo(filename); - ownerId = fileInfo.ownerId(); - groupId = fileInfo.groupId(); - } + QScopedPointer saveFile(new QFile(filename)); /** - * use QSaveFile for file saving + * if we want to use kauth anyways or we can open the file write only => use buffer and try to use authhelper */ - QScopedPointer saveFile(new QSaveFile(filename)); - static_cast(saveFile.data())->setDirectWriteFallback(true); - + uint ownerId = -2; + uint groupId = -2; bool usingTemporaryBuffer = false; - - // open QSaveFile for write if (m_alwaysUseKAuthForSave || !saveFile->open(QIODevice::WriteOnly)) { + /** + * 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 - usingTemporaryBuffer = true; // we are now saving to a temporary buffer @@ -809,7 +805,6 @@ */ KCompressionDevice::CompressionType type = KFilterDev::compressionTypeForMimeType(m_mimeTypeForFilterDev); KCompressionDevice file(saveFile.data(), false, type); - if (!file.open(QIODevice::WriteOnly)) { return false; } @@ -859,112 +854,84 @@ // flush stream stream.flush(); - // close and delete file + // close file file.close(); - // flush file + // flush file, if not a QBuffer if (!usingTemporaryBuffer) { - static_cast(saveFile.data())->flush(); + static_cast(saveFile.data())->flush(); } // did save work? // only finalize if stream status == OK - bool ok = (stream.status() == QTextStream::Ok); - - // commit changes - if (ok) { + if (stream.status() != QTextStream::Ok) { + return false; + } - if (usingTemporaryBuffer) { + /** + * if we used a QBuffer for kauth, try to move that to the real location with the helper + */ + if (usingTemporaryBuffer) { + // temporary buffer was used to save the file + // -> computing checksum + // -> saving to temporary file + // -> copying the temporary file to the original file location with KAuth action + QTemporaryFile tempFile; + if (!tempFile.open()) { + return false; + } - // temporary buffer was used to save the file - // -> computing checksum - // -> saving to temporary file - // -> copying the temporary file to the original file location with KAuth action + // go to QBuffer start + saveFile->seek(0); - QTemporaryFile tempFile; - if (!tempFile.open()) { - return false; - } - QCryptographicHash cryptographicHash(SecureTextBuffer::checksumAlgorithm); - - // go to QBuffer start - saveFile->seek(0); - - // read contents of QBuffer and add them to checksum utility as well as to QTemporaryFile - char buffer[bufferLength]; - qint64 read = -1; - while ((read = saveFile->read(buffer, bufferLength)) > 0) { - cryptographicHash.addData(buffer, read); - if (tempFile.write(buffer, read) == -1) { - return false; - } - } - if (!tempFile.flush()) { + // read contents of QBuffer and add them to checksum utility as well as to QTemporaryFile + char buffer[bufferLength]; + qint64 read = -1; + QCryptographicHash cryptographicHash(SecureTextBuffer::checksumAlgorithm); + while ((read = saveFile->read(buffer, bufferLength)) > 0) { + cryptographicHash.addData(buffer, read); + if (tempFile.write(buffer, read) == -1) { return false; } + } + if (!tempFile.flush()) { + return false; + } - // compute checksum - QByteArray checksum = cryptographicHash.result(); - - // prepare data for KAuth action - QVariantMap kAuthActionArgs; - kAuthActionArgs.insert(QLatin1String("sourceFile"), tempFile.fileName()); - kAuthActionArgs.insert(QLatin1String("targetFile"), filename); - kAuthActionArgs.insert(QLatin1String("checksum"), checksum); - kAuthActionArgs.insert(QLatin1String("ownerId"), ownerId); - kAuthActionArgs.insert(QLatin1String("groupId"), groupId); - - // call save with elevated privileges - if (KTextEditor::EditorPrivate::unitTestMode()) { - - // unit testing purposes only - ok = SecureTextBuffer::savefile(kAuthActionArgs).succeeded(); - - } else { - - KAuth::Action kAuthSaveAction(QLatin1String("org.kde.ktexteditor.katetextbuffer.savefile")); - kAuthSaveAction.setHelperId(QLatin1String("org.kde.ktexteditor.katetextbuffer")); - kAuthSaveAction.setArguments(kAuthActionArgs); - KAuth::ExecuteJob *job = kAuthSaveAction.execute(); - ok = job->exec(); - + // prepare data for KAuth action + QVariantMap kAuthActionArgs; + kAuthActionArgs.insert(QLatin1String("sourceFile"), tempFile.fileName()); + kAuthActionArgs.insert(QLatin1String("targetFile"), filename); + kAuthActionArgs.insert(QLatin1String("checksum"), cryptographicHash.result()); + kAuthActionArgs.insert(QLatin1String("ownerId"), ownerId); + kAuthActionArgs.insert(QLatin1String("groupId"), groupId); + + // call save with elevated privileges + if (KTextEditor::EditorPrivate::unitTestMode()) { + // unit testing purposes only + if (!SecureTextBuffer::savefile(kAuthActionArgs).succeeded()) { + return false; } - } else { - - // standard save without elevated privileges - - QSaveFile *saveFileLocal = static_cast(saveFile.data()); - - if (!newFile) { - // ensure correct owner - SecureTextBuffer::setOwner(saveFileLocal->handle(), ownerId, groupId); + KAuth::Action kAuthSaveAction(QLatin1String("org.kde.ktexteditor.katetextbuffer.savefile")); + kAuthSaveAction.setHelperId(QLatin1String("org.kde.ktexteditor.katetextbuffer")); + kAuthSaveAction.setArguments(kAuthActionArgs); + KAuth::ExecuteJob *job = kAuthSaveAction.execute(); + if (!job->exec()) { + return false; } - - ok = saveFileLocal->commit(); - } } - // remember this revision as last saved if we had success! - if (ok) { - m_history.setLastSavedRevision(); - } - - // report CODEC + ERRORS - BUFFER_DEBUG << "Saved file " << filename << "with codec" << m_textCodec->name() << (ok ? "without" : "with") << "errors"; - - if (ok) { - markModifiedLinesAsSaved(); - } + // remember this revision as last saved + m_history.setLastSavedRevision(); - // emit signal on success - if (ok) { - emit saved(filename); - } + // inform that we have saved the state + markModifiedLinesAsSaved(); - // return success or not - return ok; + // emit that file was saved and be done + emit saved(filename); + return true; } void TextBuffer::notifyAboutRangeChange(KTextEditor::View *view, int startLine, int endLine, bool rangeWithAttribute) diff --git a/src/document/katedocument.cpp b/src/document/katedocument.cpp --- a/src/document/katedocument.cpp +++ b/src/document/katedocument.cpp @@ -2409,7 +2409,7 @@ if (!m_buffer->saveFile(localFilePath())) { // add m_file again to dirwatch activateDirWatch(oldPath); - KMessageBox::error(dialogParent(), i18n("The document could not be saved, as it was not possible to write to %1.\n\nCheck that you have write access to this file or that enough disk space is available.", this->url().toDisplayString(QUrl::PreferLocalFile))); + KMessageBox::error(dialogParent(), i18n("The document could not be saved, as it was not possible to write to %1.\nCheck that you have write access to this file or that enough disk space is available.\nThe original file may be lost or damaged. Don't quit the application until the file is successfully written.", this->url().toDisplayString(QUrl::PreferLocalFile))); return false; } diff --git a/src/export/exporter.cpp b/src/export/exporter.cpp --- a/src/export/exporter.cpp +++ b/src/export/exporter.cpp @@ -36,7 +36,6 @@ #include #include #include -#include void KateExporter::exportToClipboard() {