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 ?