Changeset View
Changeset View
Standalone View
Standalone View
src/utils/output.cpp
Show All 27 Lines | 1 | /* -*- mode: c++; c-basic-offset:4 -*- | |||
---|---|---|---|---|---|
28 | your version of the file, but you are not obligated to do so. If | 28 | your version of the file, but you are not obligated to do so. If | ||
29 | you do not wish to do so, delete this exception statement from | 29 | you do not wish to do so, delete this exception statement from | ||
30 | your version. | 30 | your version. | ||
31 | */ | 31 | */ | ||
32 | 32 | | |||
33 | #include <config-kleopatra.h> | 33 | #include <config-kleopatra.h> | ||
34 | 34 | | |||
35 | #include "output.h" | 35 | #include "output.h" | ||
36 | 36 | #include "input_p.h" | |||
37 | #include "detail_p.h" | 37 | #include "detail_p.h" | ||
38 | #include "kleo_assert.h" | 38 | #include "kleo_assert.h" | ||
39 | #include "kdpipeiodevice.h" | 39 | #include "kdpipeiodevice.h" | ||
40 | #include "log.h" | 40 | #include "log.h" | ||
41 | #include "cached.h" | 41 | #include "cached.h" | ||
42 | 42 | | |||
43 | #include <Libkleo/Exception> | 43 | #include <Libkleo/Exception> | ||
44 | 44 | | |||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Line(s) | 159 | struct redirect_close : T_IODevice { | |||
170 | bool isClosed() const | 170 | bool isClosed() const | ||
171 | { | 171 | { | ||
172 | return m_closed; | 172 | return m_closed; | ||
173 | } | 173 | } | ||
174 | private: | 174 | private: | ||
175 | bool m_closed; | 175 | bool m_closed; | ||
176 | }; | 176 | }; | ||
177 | 177 | | |||
178 | class FileOutput; | ||||
179 | class OutputInput : public InputImplBase | ||||
180 | { | ||||
181 | public: | ||||
182 | OutputInput(const std::shared_ptr<FileOutput> &output); | ||||
183 | | ||||
184 | unsigned int classification() const override | ||||
185 | { | ||||
186 | return 0; | ||||
187 | } | ||||
188 | | ||||
189 | void outputFinalized() | ||||
190 | { | ||||
191 | if (!m_ioDevice->open(QIODevice::ReadOnly)) { | ||||
192 | qCCritical(KLEOPATRA_LOG) << "Failed to open file for reading"; | ||||
193 | } | ||||
194 | } | ||||
195 | | ||||
196 | std::shared_ptr<QIODevice> ioDevice() const override | ||||
197 | { | ||||
198 | return m_ioDevice; | ||||
199 | } | ||||
200 | | ||||
201 | unsigned long long size() const override | ||||
202 | { | ||||
203 | return 0; | ||||
204 | } | ||||
205 | | ||||
206 | private: | ||||
207 | std::shared_ptr<FileOutput> m_output; | ||||
208 | mutable std::shared_ptr<QIODevice> m_ioDevice = nullptr; | ||||
209 | }; | ||||
210 | | ||||
178 | class OutputImplBase : public Output | 211 | class OutputImplBase : public Output | ||
179 | { | 212 | { | ||
180 | public: | 213 | public: | ||
181 | OutputImplBase() | 214 | OutputImplBase() | ||
182 | : Output(), | 215 | : Output(), | ||
183 | m_defaultLabel(), | 216 | m_defaultLabel(), | ||
184 | m_customLabel(), | 217 | m_customLabel(), | ||
185 | m_errorString(), | 218 | m_errorString(), | ||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Line(s) | 383 | public: | |||
361 | std::shared_ptr<QIODevice> ioDevice() const override | 394 | std::shared_ptr<QIODevice> ioDevice() const override | ||
362 | { | 395 | { | ||
363 | return m_tmpFile; | 396 | return m_tmpFile; | ||
364 | } | 397 | } | ||
365 | void doFinalize() override; | 398 | void doFinalize() override; | ||
366 | void doCancel() override { | 399 | void doCancel() override { | ||
367 | qCDebug(KLEOPATRA_LOG) << this; | 400 | qCDebug(KLEOPATRA_LOG) << this; | ||
368 | } | 401 | } | ||
402 | QString fileName() const | ||||
403 | { | ||||
404 | return m_fileName; | ||||
405 | } | ||||
406 | | ||||
407 | void attachInput(const std::shared_ptr<OutputInput> &input) | ||||
408 | { | ||||
409 | m_attachedInput = std::weak_ptr<OutputInput>(input); | ||||
410 | } | ||||
411 | | ||||
369 | private: | 412 | private: | ||
370 | bool obtainOverwritePermission(); | 413 | bool obtainOverwritePermission(); | ||
371 | 414 | | |||
372 | private: | 415 | private: | ||
373 | const QString m_fileName; | 416 | const QString m_fileName; | ||
374 | std::shared_ptr< TemporaryFile > m_tmpFile; | 417 | std::shared_ptr< TemporaryFile > m_tmpFile; | ||
375 | const std::shared_ptr<OverwritePolicy> m_policy; | 418 | const std::shared_ptr<OverwritePolicy> m_policy; | ||
419 | std::weak_ptr<OutputInput> m_attachedInput; | ||||
376 | }; | 420 | }; | ||
377 | 421 | | |||
378 | #ifndef QT_NO_CLIPBOARD | 422 | #ifndef QT_NO_CLIPBOARD | ||
379 | class ClipboardOutput : public OutputImplBase | 423 | class ClipboardOutput : public OutputImplBase | ||
380 | { | 424 | { | ||
381 | public: | 425 | public: | ||
382 | explicit ClipboardOutput(QClipboard::Mode mode); | 426 | explicit ClipboardOutput(QClipboard::Mode mode); | ||
383 | 427 | | |||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Line(s) | 510 | { | |||
488 | QPointer<QObject> guard = m_tmpFile.get(); | 532 | QPointer<QObject> guard = m_tmpFile.get(); | ||
489 | m_tmpFile.reset(); // really close the file - needed on Windows for renaming :/ | 533 | m_tmpFile.reset(); // really close the file - needed on Windows for renaming :/ | ||
490 | kleo_assert(!guard); // if this triggers, we need to audit for holder of std::shared_ptr<QIODevice>s. | 534 | kleo_assert(!guard); // if this triggers, we need to audit for holder of std::shared_ptr<QIODevice>s. | ||
491 | 535 | | |||
492 | qCDebug(KLEOPATRA_LOG) << this << " renaming " << tmpFileName << "->" << m_fileName; | 536 | qCDebug(KLEOPATRA_LOG) << this << " renaming " << tmpFileName << "->" << m_fileName; | ||
493 | 537 | | |||
494 | if (QFile::rename(tmpFileName, m_fileName)) { | 538 | if (QFile::rename(tmpFileName, m_fileName)) { | ||
495 | qCDebug(KLEOPATRA_LOG) << this << "succeeded"; | 539 | qCDebug(KLEOPATRA_LOG) << this << "succeeded"; | ||
540 | | ||||
541 | if (!m_attachedInput.expired()) { | ||||
542 | m_attachedInput.lock()->outputFinalized(); | ||||
543 | } | ||||
496 | return; | 544 | return; | ||
497 | } | 545 | } | ||
498 | 546 | | |||
499 | qCDebug(KLEOPATRA_LOG) << this << "failed"; | 547 | qCDebug(KLEOPATRA_LOG) << this << "failed"; | ||
500 | 548 | | |||
501 | if (!obtainOverwritePermission()) | 549 | if (!obtainOverwritePermission()) | ||
502 | throw Exception(gpg_error(GPG_ERR_CANCELED), | 550 | throw Exception(gpg_error(GPG_ERR_CANCELED), | ||
503 | i18n("Overwriting declined")); | 551 | i18n("Overwriting declined")); | ||
504 | 552 | | |||
505 | qCDebug(KLEOPATRA_LOG) << this << "going to overwrite" << m_fileName; | 553 | qCDebug(KLEOPATRA_LOG) << this << "going to overwrite" << m_fileName; | ||
506 | 554 | | |||
507 | if (!QFile::remove(m_fileName)) | 555 | if (!QFile::remove(m_fileName)) | ||
508 | throw Exception(errno ? gpg_error_from_errno(errno) : gpg_error(GPG_ERR_EIO), | 556 | throw Exception(errno ? gpg_error_from_errno(errno) : gpg_error(GPG_ERR_EIO), | ||
509 | i18n("Could not remove file \"%1\" for overwriting.", m_fileName)); | 557 | i18n("Could not remove file \"%1\" for overwriting.", m_fileName)); | ||
510 | 558 | | |||
511 | qCDebug(KLEOPATRA_LOG) << this << "succeeded, renaming " << tmpFileName << "->" << m_fileName; | 559 | qCDebug(KLEOPATRA_LOG) << this << "succeeded, renaming " << tmpFileName << "->" << m_fileName; | ||
512 | 560 | | |||
513 | if (QFile::rename(tmpFileName, m_fileName)) { | 561 | if (QFile::rename(tmpFileName, m_fileName)) { | ||
514 | qCDebug(KLEOPATRA_LOG) << this << "succeeded"; | 562 | qCDebug(KLEOPATRA_LOG) << this << "succeeded"; | ||
563 | | ||||
564 | if (!m_attachedInput.expired()) { | ||||
565 | m_attachedInput.lock()->outputFinalized(); | ||||
566 | } | ||||
515 | return; | 567 | return; | ||
516 | } | 568 | } | ||
517 | 569 | | |||
518 | qCDebug(KLEOPATRA_LOG) << this << "failed"; | 570 | qCDebug(KLEOPATRA_LOG) << this << "failed"; | ||
519 | 571 | | |||
520 | throw Exception(errno ? gpg_error_from_errno(errno) : gpg_error(GPG_ERR_EIO), | 572 | throw Exception(errno ? gpg_error_from_errno(errno) : gpg_error(GPG_ERR_EIO), | ||
521 | i18n("Could not rename file \"%1\" to \"%2\"", | 573 | i18n("Could not rename file \"%1\" to \"%2\"", | ||
522 | tmpFileName, m_fileName)); | 574 | tmpFileName, m_fileName)); | ||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Line(s) | 673 | if (QClipboard *const cb = QApplication::clipboard()) { | |||
622 | cb->setText(QString::fromUtf8(m_buffer->data())); | 674 | cb->setText(QString::fromUtf8(m_buffer->data())); | ||
623 | } else | 675 | } else | ||
624 | throw Exception(gpg_error(GPG_ERR_EIO), | 676 | throw Exception(gpg_error(GPG_ERR_EIO), | ||
625 | i18n("Could not find clipboard")); | 677 | i18n("Could not find clipboard")); | ||
626 | } | 678 | } | ||
627 | #endif // QT_NO_CLIPBOARD | 679 | #endif // QT_NO_CLIPBOARD | ||
628 | 680 | | |||
629 | Output::~Output() {} | 681 | Output::~Output() {} | ||
682 | | ||||
683 | | ||||
684 | OutputInput::OutputInput(const std::shared_ptr<FileOutput> &output) | ||||
685 | : m_output(output) | ||||
686 | , m_ioDevice(new QFile(output->fileName())) | ||||
mlaurent: mem leak or not mem leak ? | |||||
dvratil: m_ioDevice is an std::shared_ptr, so not a mem leak :-) | |||||
687 | { | ||||
688 | } | ||||
689 | | ||||
690 | | ||||
691 | | ||||
692 | std::shared_ptr<Input> Input::createFromOutput(const std::shared_ptr<Output> &output) | ||||
693 | { | ||||
694 | if (auto fo = std::dynamic_pointer_cast<FileOutput>(output)) { | ||||
695 | auto input = std::shared_ptr<OutputInput>(new OutputInput(fo)); | ||||
696 | fo->attachInput(input); | ||||
697 | return input; | ||||
698 | } else { | ||||
699 | return {}; | ||||
700 | } | ||||
701 | } |
mem leak or not mem leak ?