File indexing completed on 2024-05-12 05:17:23

0001 /*
0002     Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
0003     Copyright (c) 2009 Andras Mantia <amantia@kde.org>
0004     Copyright (c) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
0005 
0006     This library is free software; you can redistribute it and/or modify it
0007     under the terms of the GNU Library General Public License as published by
0008     the Free Software Foundation; either version 2 of the License, or (at your
0009     option) any later version.
0010 
0011     This library is distributed in the hope that it will be useful, but WITHOUT
0012     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0014     License for more details.
0015 
0016     You should have received a copy of the GNU Library General Public License
0017     along with this library; see the file COPYING.LIB.  If not, write to the
0018     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0019     02110-1301, USA.
0020 */
0021 
0022 #ifndef KIMAP2_IMAPSTREAMPARSER_P_H
0023 #define KIMAP2_IMAPSTREAMPARSER_P_H
0024 
0025 #include "kimap2_export.h"
0026 
0027 #include <QtCore/QByteArray>
0028 #include <QtCore/QList>
0029 #include <QtCore/QScopedPointer>
0030 #include <functional>
0031 #include <message_p.h>
0032 
0033 class QIODevice;
0034 
0035 namespace KIMAP2
0036 {
0037 
0038 /**
0039   Parser for IMAP messages that operates on a local socket stream.
0040 */
0041 class KIMAP2_EXPORT ImapStreamParser
0042 {
0043 public:
0044     /**
0045      * Construct the parser.
0046      * @param socket the local socket to work with.
0047      * @param serverModeEnabled true if the parser has to assume we're writing a server (e.g. sends
0048      * continuation message automatically)
0049      */
0050     explicit ImapStreamParser(QIODevice *socket, bool serverModeEnabled = false);
0051 
0052     /**
0053      * Return everything that remained from the command.
0054      * @return the remaining command data
0055      */
0056     QByteArray readUntilCommandEnd();
0057 
0058     int availableDataSize() const;
0059 
0060     void parseStream();
0061 
0062     void onResponseReceived(std::function<void(const Message &)>);
0063 
0064     bool error() const;
0065 
0066     QByteArray currentBuffer() const;
0067 
0068 private:
0069 
0070     /**
0071      * Remove already read data from the internal buffer if necessary.
0072      */
0073     void trimBuffer();
0074 
0075     /**
0076      * Inform the client to send more literal data.
0077      */
0078     void sendContinuationResponse(qint64 size);
0079 
0080 
0081     int readFromSocket();
0082     void processBuffer();
0083 
0084     char at(int pos) const;
0085     QByteArray mid(int start, int end = -1)  const;
0086     QByteArray midRef(int start, int end)  const;
0087     int length() const;
0088 
0089     QByteArray &buffer();
0090     const QByteArray &buffer() const;
0091 
0092     QScopedPointer<Message> m_message;
0093     QList<Message::Part> *m_currentPayload;
0094 
0095     QIODevice *m_socket;
0096     bool m_isServerModeEnabled;
0097     bool m_processing;
0098     int m_position;
0099     int m_readPosition;
0100     qint64 m_literalSize;
0101     QByteArray m_data1;
0102     QByteArray m_data2;
0103     QByteArray *m_current;
0104     int m_bufferSize;
0105 
0106     enum States {
0107         InitState,
0108         QuotedStringState,
0109         LiteralStringState,
0110         StringState,
0111         WhitespaceState,
0112         AngleBracketStringState,
0113         SublistString,
0114         CRLFState
0115     };
0116     States m_currentState;
0117     States m_lastState;
0118 
0119     void setState(States state);
0120     void forwardToState(States state);
0121     void resetState();
0122 
0123     int m_listCounter;
0124     int m_stringStartPos;
0125     bool m_readingLiteral;
0126     bool m_error;
0127 
0128     std::function<void(const char *data, const int size)> string;
0129     std::function<void()> listStart;
0130     std::function<void()> listEnd;
0131     std::function<void()> responseCodeStart;
0132     std::function<void()> responseCodeEnd;
0133     std::function<void(int size)> literalStart;
0134     std::function<void(const char *data, const int size)> literalPart;
0135     std::function<void()> literalEnd;
0136     std::function<void()> lineEnd;
0137 
0138     void onString(std::function<void(const char *data, const int size)> f)
0139     {
0140         string = f;
0141     }
0142 
0143     void onListStart(std::function<void()> f)
0144     {
0145         listStart = f;
0146     }
0147 
0148     void onListEnd(std::function<void()> f)
0149     {
0150         listEnd = f;
0151     }
0152 
0153     void onResponseCodeStart(std::function<void()> f)
0154     {
0155         responseCodeStart = f;
0156     }
0157 
0158     void onResponseCodeEnd(std::function<void()> f)
0159     {
0160         responseCodeEnd = f;
0161     }
0162 
0163     void onLiteralStart(std::function<void(int size)> f)
0164     {
0165         literalStart = f;
0166     }
0167 
0168     void onLiteralPart(std::function<void(const char *data, const int size)> f)
0169     {
0170         literalPart = f;
0171     }
0172 
0173     void onLiteralEnd(std::function<void()> f)
0174     {
0175         literalEnd = f;
0176     }
0177 
0178     void onLineEnd(std::function<void()> f)
0179     {
0180         lineEnd = f;
0181     }
0182 
0183     std::function<void(const Message &)> responseReceived;
0184 
0185     void setupCallbacks();
0186 
0187     QList<QByteArray> *m_list;
0188     QByteArray m_literalData;
0189 };
0190 
0191 }
0192 
0193 #endif