Changeset View
Changeset View
Standalone View
Standalone View
src/buffer/katetextbuffer.cpp
Context not available. | |||||
35 | #endif | 35 | #endif | ||
---|---|---|---|---|---|
36 | 36 | | |||
37 | #include <QSaveFile> | 37 | #include <QSaveFile> | ||
38 | #include <QTemporaryFile> | 38 | #include <QBuffer> | ||
39 | #include <QFileDevice> | | |||
40 | #include <QFileInfo> | 39 | #include <QFileInfo> | ||
41 | 40 | | |||
42 | #if 0 | 41 | #if 0 | ||
Context not available. | |||||
48 | namespace Kate | 47 | namespace Kate | ||
49 | { | 48 | { | ||
50 | 49 | | |||
51 | TextBuffer::TextBuffer(KTextEditor::DocumentPrivate *parent, int blockSize, bool alwaysUseKAuth) | 50 | TextBuffer::TextBuffer(KTextEditor::DocumentPrivate *parent, int blockSize) | ||
52 | : QObject(parent) | 51 | : QObject(parent) | ||
53 | , m_document(parent) | 52 | , m_document(parent) | ||
54 | , m_history(*this) | 53 | , m_history(*this) | ||
Context not available. | |||||
68 | , m_endOfLineMode(eolUnix) | 67 | , m_endOfLineMode(eolUnix) | ||
69 | , m_newLineAtEof(false) | 68 | , m_newLineAtEof(false) | ||
70 | , m_lineLengthLimit(4096) | 69 | , m_lineLengthLimit(4096) | ||
71 | , m_alwaysUseKAuthForSave(alwaysUseKAuth) | | |||
72 | { | 70 | { | ||
73 | // minimal block size must be > 0 | 71 | // minimal block size must be > 0 | ||
74 | Q_ASSERT(m_blockSize > 0); | 72 | Q_ASSERT(m_blockSize > 0); | ||
Context not available. | |||||
779 | } | 777 | } | ||
780 | 778 | | |||
781 | /** | 779 | /** | ||
782 | * use QSaveFile for save write + rename | 780 | * use QSaveFile for file saving | ||
783 | */ | 781 | */ | ||
784 | QScopedPointer<QFileDevice> saveFile(new QSaveFile(filename)); | 782 | QScopedPointer<QIODevice> saveFile(new QSaveFile(filename)); | ||
785 | static_cast<QSaveFile *>(saveFile.data())->setDirectWriteFallback(true); | 783 | static_cast<QSaveFile *>(saveFile.data())->setDirectWriteFallback(true); | ||
786 | 784 | | |||
787 | bool usingTemporaryFile = false; | 785 | bool usingTemporaryBuffer = false; | ||
788 | QScopedPointer<QVariantMap> kAuthActionArgs; | | |||
789 | QScopedPointer<KAuth::Action> kAuthSaveAction; | | |||
790 | 786 | | |||
791 | // open QSaveFile for write | 787 | // open QSaveFile for write | ||
792 | if (m_alwaysUseKAuthForSave || !saveFile->open(QIODevice::WriteOnly)) { | 788 | if (!saveFile->open(QIODevice::WriteOnly)) { | ||
793 | 789 | | |||
794 | // if that fails we need more privileges to save this file | 790 | // if that fails we need more privileges to save this file | ||
795 | // -> we write to temporary file and then move it to target location | 791 | // -> we write to a temporary buffer and then send it to KAuth action for privileged save | ||
796 | 792 | | |||
797 | usingTemporaryFile = true; | 793 | usingTemporaryBuffer = true; | ||
798 | 794 | | |||
799 | QString targetFilename(filename); | 795 | // we are now saving to a prepared temporary buffer | ||
796 | saveFile.reset(new QBuffer()); | ||||
800 | 797 | | |||
801 | kAuthActionArgs.reset(new QVariantMap()); | 798 | // open QBuffer for write | ||
802 | kAuthActionArgs->insert(QLatin1String("actionMode"), SecureTextBuffer::ActionMode::Prepare); | | |||
803 | kAuthActionArgs->insert(QLatin1String("targetFile"), targetFilename); | | |||
804 | kAuthActionArgs->insert(QLatin1String("ownerId"), getuid()); | | |||
805 | | ||||
806 | // call save with elevated privileges | | |||
807 | if (KTextEditor::EditorPrivate::unitTestMode()) { | | |||
808 | | ||||
809 | // unit testing purposes only | | |||
810 | ActionReply reply = SecureTextBuffer::savefile(*kAuthActionArgs); | | |||
811 | if (!reply.succeeded()) { | | |||
812 | return false; | | |||
813 | } | | |||
814 | targetFilename = reply.data()[QLatin1String("temporaryFile")].toString(); | | |||
815 | | ||||
816 | } else { | | |||
817 | | ||||
818 | // call action | | |||
819 | kAuthSaveAction.reset(new KAuth::Action(QLatin1String("org.kde.ktexteditor.katetextbuffer.savefile"))); | | |||
820 | kAuthSaveAction->setHelperId(QLatin1String("org.kde.ktexteditor.katetextbuffer")); | | |||
821 | kAuthSaveAction->setArguments(*kAuthActionArgs); | | |||
822 | KAuth::ExecuteJob *job = kAuthSaveAction->execute(); | | |||
823 | if (!job->exec()) { | | |||
824 | return false; | | |||
825 | } | | |||
826 | | ||||
827 | // get temporary file path from the reply | | |||
828 | targetFilename = job->data()[QLatin1String("temporaryFile")].toString(); | | |||
829 | | ||||
830 | } | | |||
831 | | ||||
832 | if (targetFilename.isEmpty()) { | | |||
833 | return false; | | |||
834 | } | | |||
835 | | ||||
836 | // we are now saving to a prepared temporary file | | |||
837 | saveFile.reset(new QFile(targetFilename)); | | |||
838 | | ||||
839 | // open QTemporaryFile for write | | |||
840 | if (!saveFile->open(QIODevice::WriteOnly)) { | 799 | if (!saveFile->open(QIODevice::WriteOnly)) { | ||
841 | return false; | 800 | return false; | ||
842 | } | 801 | } | ||
843 | | ||||
844 | if (!newFile) { | | |||
845 | // set original file's permissions to temporary file (QSaveFile does this automatically) | | |||
846 | saveFile->setPermissions(QFile(filename).permissions()); | | |||
847 | } | | |||
848 | } | 802 | } | ||
849 | 803 | | |||
850 | /** | 804 | /** | ||
Context not available. | |||||
878 | } | 832 | } | ||
879 | 833 | | |||
880 | // just dump the lines out ;) | 834 | // just dump the lines out ;) | ||
835 | qint64 writtenTextLength = 0; | ||||
881 | for (int i = 0; i < m_lines; ++i) { | 836 | for (int i = 0; i < m_lines; ++i) { | ||
882 | // get line to save | 837 | // get line to save | ||
883 | Kate::TextLine textline = line(i); | 838 | Kate::TextLine textline = line(i); | ||
839 | QString line = textline->text(); | ||||
840 | | ||||
841 | // limit RAM usage in case of using QBuffer | ||||
842 | if (usingTemporaryBuffer) { | ||||
843 | writtenTextLength += line.size() + 1; | ||||
844 | if (writtenTextLength > temporaryBufferMaxSize) { | ||||
845 | // buffer max size exceeded, bailing out | ||||
846 | return false; | ||||
847 | } | ||||
848 | } | ||||
884 | 849 | | |||
885 | stream << textline->text(); | 850 | stream << line; | ||
886 | 851 | | |||
887 | // append correct end of line string | 852 | // append correct end of line string | ||
888 | if ((i + 1) < m_lines) { | 853 | if ((i + 1) < m_lines) { | ||
Context not available. | |||||
906 | file.close(); | 871 | file.close(); | ||
907 | 872 | | |||
908 | // flush file | 873 | // flush file | ||
909 | if (!saveFile->flush()) { | 874 | if (!usingTemporaryBuffer) { | ||
910 | return false; | 875 | if (!static_cast<QSaveFile *>(saveFile.data())->flush()) { | ||
911 | } | 876 | return false; | ||
912 | 877 | } | |||
913 | if (usingTemporaryFile) { | | |||
914 | // ensure that the file is written to disk | | |||
915 | // just for temporary file (QSaveFile does this automatically in commit()) | | |||
916 | SecureTextBuffer::syncToDisk(saveFile->handle()); | | |||
917 | } | 878 | } | ||
918 | 879 | | |||
919 | // did save work? | 880 | // did save work? | ||
Context not available. | |||||
923 | // commit changes | 884 | // commit changes | ||
924 | if (ok) { | 885 | if (ok) { | ||
925 | 886 | | |||
926 | if (usingTemporaryFile) { | 887 | if (usingTemporaryBuffer) { | ||
927 | 888 | | |||
928 | // temporary file was used to save the file | 889 | // temporary file was used to save the file | ||
929 | // -> moving this file to original location with KAuth action | 890 | // -> moving this file to original location with KAuth action | ||
930 | 891 | | |||
931 | kAuthActionArgs->insert(QLatin1String("actionMode"), SecureTextBuffer::ActionMode::Move); | 892 | QVariantMap kAuthActionArgs; | ||
932 | kAuthActionArgs->insert(QLatin1String("sourceFile"), saveFile->fileName()); | 893 | kAuthActionArgs.insert(QLatin1String("targetFile"), filename); | ||
933 | kAuthActionArgs->insert(QLatin1String("targetFile"), filename); | 894 | kAuthActionArgs.insert(QLatin1String("fileData"), static_cast<QBuffer *>(saveFile.data())->data()); | ||
934 | kAuthActionArgs->insert(QLatin1String("ownerId"), ownerId); | 895 | kAuthActionArgs.insert(QLatin1String("ownerId"), ownerId); | ||
935 | kAuthActionArgs->insert(QLatin1String("groupId"), groupId); | 896 | kAuthActionArgs.insert(QLatin1String("groupId"), groupId); | ||
936 | 897 | | |||
937 | // call save with elevated privileges | 898 | // call save with elevated privileges | ||
938 | if (KTextEditor::EditorPrivate::unitTestMode()) { | 899 | if (KTextEditor::EditorPrivate::unitTestMode()) { | ||
939 | 900 | | |||
940 | // unit testing purposes only | 901 | // unit testing purposes only | ||
941 | ok = SecureTextBuffer::savefile(*kAuthActionArgs).succeeded(); | 902 | ok = SecureTextBuffer::savefile(kAuthActionArgs).succeeded(); | ||
942 | 903 | | |||
943 | } else { | 904 | } else { | ||
944 | 905 | | |||
945 | kAuthSaveAction->setArguments(*kAuthActionArgs); | 906 | KAuth::Action kAuthSaveAction(QLatin1String("org.kde.ktexteditor.katetextbuffer.savefile")); | ||
946 | KAuth::ExecuteJob *job = kAuthSaveAction->execute(); | 907 | kAuthSaveAction.setHelperId(QLatin1String("org.kde.ktexteditor.katetextbuffer")); | ||
908 | kAuthSaveAction.setArguments(kAuthActionArgs); | ||||
909 | KAuth::ExecuteJob *job = kAuthSaveAction.execute(); | ||||
947 | ok = job->exec(); | 910 | ok = job->exec(); | ||
948 | 911 | | |||
949 | } | 912 | } | ||
Context not available. |