File indexing completed on 2024-04-28 05:18:35

0001 /*
0002     SPDX-FileCopyrightText: 2009 Bertjan Broeksema <broeksema@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "kmbox_export.h"
0010 #include "mboxentry.h"
0011 #include <memory>
0012 
0013 #include <KMime/KMimeMessage>
0014 
0015 namespace KMBox
0016 {
0017 class MBoxPrivate;
0018 
0019 /**
0020  * @short A class to access mail storages in MBox format.
0021  *
0022  * @author Bertjan Broeksema <broeksema@kde.org>
0023  * @since 4.6
0024  */
0025 class KMBOX_EXPORT MBox
0026 {
0027 public:
0028     /**
0029      * Describes the type of locking that will be used.
0030      */
0031     enum LockType { ProcmailLockfile, MuttDotlock, MuttDotlockPrivileged, None };
0032 
0033     /**
0034      * Creates a new mbox object.
0035      */
0036     MBox();
0037 
0038     /**
0039      * Destroys the mbox object.
0040      *
0041      * The file will be unlocked if it is still open.
0042      */
0043     ~MBox();
0044 
0045     /**
0046      * Appends @p message to the MBox and returns the corresponding mbox entry for it.
0047      * You must load a mbox file by making a call to load( const QString& ) before
0048      * appending entries.
0049      * The returned mbox entry is <em>only</em> valid for that particular file.
0050      *
0051      * @param message The message to append to the mbox.
0052      * @return the corresponding mbox entry for the message in the file or an invalid mbox entry
0053      *         if the message was not added.
0054      */
0055     [[nodiscard]] MBoxEntry appendMessage(const KMime::Message::Ptr &message);
0056 
0057     /**
0058      * Retrieve the mbox entry objects for all emails from the file except the
0059      * @p deleteEntries.
0060      * The @p deletedEntries should be a list of mbox entries with offsets of deleted messages.
0061      * @param deletedEntries list of mbox entries that have been deleted and need not be retrieved
0062      * Note: One <em>must</em> call load() before calling this method.
0063      */
0064     [[nodiscard]] MBoxEntry::List entries(const MBoxEntry::List &deletedEntries = MBoxEntry::List()) const;
0065 
0066     /**
0067      * Returns the file name that was passed to the last call to load().
0068      */
0069     [[nodiscard]] QString fileName() const;
0070 
0071     /**
0072      * Loads the raw mbox data from disk into the current MBox object. Messages
0073      * already present are <em>not</em> preserved. This method does not load the
0074      * full messages into memory but only the offsets of the messages and their
0075      * sizes. If the file currently is locked this method will do nothing and
0076      * return false. Appended messages that are not written yet will get lost.
0077      *
0078      * @param fileName the name of the mbox on disk.
0079      * @return true, if successful, false on error.
0080      *
0081      * @see save( const QString & )
0082      */
0083     [[nodiscard]] bool load(const QString &fileName);
0084 
0085     /**
0086      * Locks the mbox file using the configured lock method. This can be used
0087      * for consecutive calls to readMessage and readMessageHeaders. Calling lock()
0088      * before these calls prevents the mbox file being locked for every call.
0089      *
0090      * NOTE: Even when the lock method is None the mbox is internally marked as
0091      *       locked. This means that it must be unlocked before calling load().
0092      *
0093      * @return true if locked successful, false on error.
0094      *
0095      * @see setLockType( LockType ), unlock()
0096      */
0097     [[nodiscard]] bool lock();
0098 
0099     /**
0100      * Returns whether or not the mbox currently is locked.
0101      */
0102     [[nodiscard]] bool locked() const;
0103 
0104     /**
0105      * Removes all messages for the given mbox entries from the current reference file
0106      * (the file that is loaded with load( const QString & ).
0107      * This method will first check if all lines at the offsets are actually
0108      * separator lines if this is not then no message will be deleted to prevent
0109      * corruption.
0110      *
0111      * @param deletedEntries The mbox entries of the messages that should be removed from
0112      *                       the file.
0113      * @param movedEntries Optional list for storing pairs of mbox entries that got moved
0114      *                     within the file due to the deletions.
0115      *                     The @c first member of the pair is the entry with the original offsets
0116      *                     the @c second member is the entry with the new (current) offset
0117      *
0118      * @return true if all offsets refer to a mbox separator line and a file was
0119      *         loaded, false otherwise. If the latter, the physical file has
0120      *         not changed.
0121      */
0122     [[nodiscard]] bool purge(const MBoxEntry::List &deletedEntries, QList<MBoxEntry::Pair> *movedEntries = nullptr);
0123 
0124     /**
0125      * Reads the entire message from the file for the given mbox @p entry. If the
0126      * mbox file is not locked this method will lock the file before reading and
0127      * unlock it after reading. If the file already is locked, it will not
0128      * unlock the file after reading the entry.
0129      *
0130      * @param entry The entry in the mbox file.
0131      * @return Message for the given entry or 0 if the file could not be locked
0132      *         or the entry offset > fileSize.
0133      *
0134      * @see lock(), unlock()
0135      */
0136     KMime::Message *readMessage(const MBoxEntry &entry);
0137 
0138     /**
0139      * Reads the headers of the message for the given mbox @p entry. If the
0140      * mbox file is not locked this method will lock the file before reading and
0141      * unlock it after reading. If the file already is locked, it will not
0142      * unlock the file after reading the entry.
0143      *
0144      * @param entry The entry in the mbox file.
0145      * @return QByteArray containing the raw message header data.
0146      *
0147      * @see lock(), unlock()
0148      */
0149     [[nodiscard]] QByteArray readMessageHeaders(const MBoxEntry &entry);
0150 
0151     /**
0152      * Reads the entire message from the file for the given mbox @p entry. If the
0153      * mbox file is not locked this method will lock the file before reading and
0154      * unlock it after reading. If the file already is locked, it will not
0155      * unlock the file after reading the entry.
0156      *
0157      * @param entry The entry in the mbox file.
0158      * @return QByteArray containing the raw message data.
0159      *
0160      * @see lock(), unlock()
0161      */
0162     [[nodiscard]] QByteArray readRawMessage(const MBoxEntry &entry);
0163 
0164     /**
0165      * Writes the mbox to disk. If the fileName is empty only appended messages
0166      * will be written to the file that was passed to load( const QString & ).
0167      * Otherwise the contents of the file that was loaded with load is copied to
0168      * @p fileName first.
0169      *
0170      * @param fileName the name of the file
0171      * @return true if the save was successful; false otherwise.
0172      *
0173      * @see load( const QString & )
0174      */
0175     [[nodiscard]] bool save(const QString &fileName = QString());
0176 
0177     /**
0178      * Sets the locktype that should be used for locking the mbox file. If the
0179      * new LockType cannot be used (e.g. the lockfile executable could not be
0180      * found) the LockType will not be changed.
0181      * @param ltype the locktype to set
0182      * This method will not do anything if the mbox object is currently locked
0183      * to make sure that it doesn't leave a locked file for one of the lockfile
0184      * / mutt_dotlock methods.
0185      */
0186     [[nodiscard]] bool setLockType(LockType ltype);
0187 
0188     /**
0189      * Sets the lockfile that should be used by the procmail or the KDE lock
0190      * file method. If this method is not called and one of the before mentioned
0191      * lock methods is used the name of the lock file will be equal to
0192      * MBOXFILENAME.lock.
0193      * @param lockFile the lockfile to set
0194      */
0195     void setLockFile(const QString &lockFile);
0196 
0197     /**
0198      * By default the unlock method will directly unlock the file. However this
0199      * is expensive in case of many consecutive calls to readEntry. Setting the
0200      * time out to a non zero value will keep the lock open until the timeout has
0201      * passed. On each read the timer will be reset.
0202      * @param msec the time out to set for file lock
0203      */
0204     void setUnlockTimeout(int msec);
0205 
0206     /**
0207      * Unlock the mbox file.
0208      *
0209      * @return true if the unlock was successful, false otherwise.
0210      *
0211      * @see lock()
0212      */
0213     [[nodiscard]] bool unlock();
0214     /**
0215      * Set the access mode of the mbox file to read only.
0216      *
0217      * If this is set to true, the mbox file can only be read from disk.
0218      * When the mbox file given in load() can not be opened in readWrite mode,
0219      * but can be opened in readOnly mode, this flag is automatically set to true.
0220      * You can still append messages, which are stored in memory
0221      * until save() is called, but the mbox can not be saved/purged to itself.
0222      * However it is possible to save it to a different file.
0223      * @param ro the readOnly flag to use
0224      *
0225      * @see save( const QString & )
0226      *
0227      * @since 4.14.5
0228      */
0229     void setReadOnly(bool ro = true);
0230 
0231     /**
0232      * Returns if the current access mode is set to readOnly.
0233      *
0234      * The access mode can either be set explicitly with setReadOnly() or
0235      * implicitly by calling load() on a readOnly file.
0236      *
0237      * @since 4.14.5
0238      */
0239     [[nodiscard]] bool isReadOnly() const;
0240 
0241 private:
0242     //@cond PRIVATE
0243     Q_DISABLE_COPY(MBox)
0244     std::unique_ptr<class MBoxPrivate> const d;
0245     //@endcond
0246 };
0247 }