/* * Copyright (C) by Michael Schuster * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #pragma once #ifndef KEYCHAINCHUNK_H #define KEYCHAINCHUNK_H #include #include #include "accountfwd.h" // We don't support insecure fallback // #define KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK namespace OCC { namespace KeychainChunk { /* * Workaround for Windows: * * Split the keychain entry's data into chunks of 2048 bytes, * to allow 4k (4096 bit) keys / large certs to be saved (see limits in webflowcredentials.h) */ static constexpr int ChunkSize = 2048; static constexpr int MaxChunks = 10; /* * @brief: Abstract base class for KeychainChunk jobs. */ class OWNCLOUDSYNC_EXPORT Job : public QObject { Q_OBJECT public: Job(QObject *parent = nullptr); virtual ~Job(); QKeychain::Error error() const; QString errorString() const; QByteArray binaryData() const; QString textData() const; bool insecureFallback() const; // If we use it but don't support insecure fallback, give us nice compilation errors ;p #if defined(KEYCHAINCHUNK_ENABLE_INSECURE_FALLBACK) void setInsecureFallback(bool insecureFallback); #endif /** * @return Whether this job autodeletes itself once finished() has been emitted. Default is true. * @see setAutoDelete() */ bool autoDelete() const; /** * Set whether this job should autodelete itself once finished() has been emitted. * @see autoDelete() */ void setAutoDelete(bool autoDelete); protected: QString _serviceName; Account *_account; QString _key; bool _insecureFallback = false; bool _autoDelete = true; bool _keychainMigration = false; QKeychain::Error _error = QKeychain::NoError; QString _errorString; int _chunkCount = 0; QByteArray _chunkBuffer; }; // class Job /* * @brief: Simple wrapper class for QKeychain::WritePasswordJob, splits too large keychain entry's data into chunks on Windows */ class OWNCLOUDSYNC_EXPORT WriteJob : public KeychainChunk::Job { Q_OBJECT public: WriteJob(Account *account, const QString &key, const QByteArray &data, QObject *parent = nullptr); WriteJob(const QString &key, const QByteArray &data, QObject *parent = nullptr); /** * Call this method to start the job (async). * You should connect some slot to the finished() signal first. * * @see QKeychain::Job::start() */ void start(); /** * Call this method to start the job synchronously. * Awaits completion with no need to connect some slot to the finished() signal first. * * @return Returns true on succeess (QKeychain::NoError). */ bool exec(); signals: void finished(KeychainChunk::WriteJob *incomingJob); private slots: void slotWriteJobDone(QKeychain::Job *incomingJob); }; // class WriteJob /* * @brief: Simple wrapper class for QKeychain::ReadPasswordJob, splits too large keychain entry's data into chunks on Windows */ class OWNCLOUDSYNC_EXPORT ReadJob : public KeychainChunk::Job { Q_OBJECT public: ReadJob(Account *account, const QString &key, bool keychainMigration, QObject *parent = nullptr); ReadJob(const QString &key, QObject *parent = nullptr); /** * Call this method to start the job (async). * You should connect some slot to the finished() signal first. * * @see QKeychain::Job::start() */ void start(); /** * Call this method to start the job synchronously. * Awaits completion with no need to connect some slot to the finished() signal first. * * @return Returns true on succeess (QKeychain::NoError). */ bool exec(); signals: void finished(KeychainChunk::ReadJob *incomingJob); private slots: void slotReadJobDone(QKeychain::Job *incomingJob); #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) private: bool _retryOnKeyChainError = true; // true if we haven't done yet any reading from keychain #endif }; // class ReadJob /* * @brief: Simple wrapper class for QKeychain::DeletePasswordJob */ class OWNCLOUDSYNC_EXPORT DeleteJob : public KeychainChunk::Job { Q_OBJECT public: DeleteJob(Account *account, const QString &key, bool keychainMigration, QObject *parent = nullptr); DeleteJob(const QString &key, QObject *parent = nullptr); /** * Call this method to start the job (async). * You should connect some slot to the finished() signal first. * * @see QKeychain::Job::start() */ void start(); /** * Call this method to start the job synchronously. * Awaits completion with no need to connect some slot to the finished() signal first. * * @return Returns true on succeess (QKeychain::NoError). */ bool exec(); signals: void finished(KeychainChunk::DeleteJob *incomingJob); private slots: void slotDeleteJobDone(QKeychain::Job *incomingJob); }; // class DeleteJob } // namespace KeychainChunk } // namespace OCC #endif // KEYCHAINCHUNK_H