File indexing completed on 2024-09-15 04:36:25

0001 /*
0002     SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "akonadiprivate_export.h"
0010 
0011 #include "imapset_p.h"
0012 
0013 #include <QByteArray>
0014 #include <QList>
0015 #include <QVarLengthArray>
0016 
0017 #include <memory>
0018 
0019 namespace Akonadi
0020 {
0021 class ImapParserPrivate;
0022 
0023 /**
0024   Parser for IMAP messages.
0025 */
0026 class AKONADIPRIVATE_EXPORT ImapParser
0027 {
0028 public:
0029     /**
0030       Parses the next parenthesized list in @p data starting from @p start
0031       and puts the result into @p result. The number of used characters is
0032       returned.
0033       This does not recurse into sub-lists.
0034       @param data Source data.
0035       @param result The parsed list.
0036       @param start Start parsing at this index.
0037     */
0038     static int parseParenthesizedList(const QByteArray &data, QList<QByteArray> &result, int start = 0);
0039     static int parseParenthesizedList(const QByteArray &data, QVarLengthArray<QByteArray, 16> &result, int start = 0);
0040 
0041     /**
0042       Parse the next string in @p data (quoted or literal) starting from @p start
0043       and puts the result into @p result. The number of used characters is returned
0044       (this is not equal to result.length()!).
0045       @param data Source data.
0046       @param result Parsed string, quotation, literal marker, etc. are removed,
0047       'NIL' is transformed into an empty QByteArray.
0048       @param start start parsing at this index.
0049     */
0050     static int parseString(const QByteArray &data, QByteArray &result, int start = 0);
0051 
0052     /**
0053       Parses the next quoted string from @p data starting at @p start and puts it into
0054       @p result. The number of parsed characters is returned (this is not equal to result.length()!).
0055       @param data Source data.
0056       @param result Parsed string, quotation is removed and 'NIL' is transformed to an empty QByteArray.
0057       @param start Start parsing at this index.
0058     */
0059     static int parseQuotedString(const QByteArray &data, QByteArray &result, int start = 0);
0060 
0061     /**
0062       Returns the number of leading spaces in @p data starting from @p start.
0063       @param data The source data.
0064       @param start Start parsing at this index.
0065     */
0066     static int stripLeadingSpaces(const QByteArray &data, int start = 0);
0067 
0068     /**
0069       Returns the parentheses balance for the given data, considering quotes.
0070       @param data The source data.
0071       @param start Start parsing at this index.
0072     */
0073     static int parenthesesBalance(const QByteArray &data, int start = 0);
0074 
0075     /**
0076       Joins a QByteArray list with the given separator.
0077       @param list The QByteArray list to join.
0078       @param separator The separator.
0079     */
0080     static QByteArray join(const QList<QByteArray> &list, const QByteArray &separator);
0081 
0082     /**
0083     Joins a QByteArray set with the given separator.
0084     @param set The QByteArray set to join.
0085     @param separator The separator.
0086      */
0087     static QByteArray join(const QSet<QByteArray> &set, const QByteArray &separator);
0088 
0089     /**
0090       Same as parseString(), but with additional UTF-8 decoding of the result.
0091       @param data Source data.
0092       @param result Parsed string, quotation, literal marker, etc. are removed,
0093       'NIL' is transformed into an empty QString. UTF-8 decoding is applied..
0094       @param start Start parsing at this index.
0095     */
0096     static int parseString(const QByteArray &data, QString &result, int start = 0);
0097 
0098     /**
0099       Parses the next integer number from @p data starting at start and puts it into
0100       @p result. The number of characters parsed is returned (this is not the parsed result!).
0101       @param data Source data.
0102       @param result Parsed integer number, invalid if ok is false.
0103       @param ok Set to false if the parsing failed.
0104       @param start Start parsing at this index.
0105     */
0106     static int parseNumber(const QByteArray &data, qint64 &result, bool *ok = nullptr, int start = 0);
0107 
0108     /**
0109       Quotes the given QByteArray.
0110       @param data Source data.
0111     */
0112     static QByteArray quote(const QByteArray &data);
0113 
0114     /**
0115       Parse an IMAP sequence set.
0116       @param data source data.
0117       @param result The parse sequence set.
0118       @param start start parsing at this index.
0119       @return end position of parsing.
0120     */
0121     static int parseSequenceSet(const QByteArray &data, ImapSet &result, int start = 0);
0122 
0123     /**
0124       Parse an IMAP date/time value.
0125       @param data source data.
0126       @param dateTime The result date/time.
0127       @param start Start parsing at this index.
0128       @return end position of parsing.
0129     */
0130     static int parseDateTime(const QByteArray &data, QDateTime &dateTime, int start = 0);
0131 
0132     /**
0133       Split a versioned key of the form 'key[version]' into its components.
0134       @param data The versioned key.
0135       @param key The unversioned key.
0136       @param version The version of the key or 0 if no version was set.
0137      */
0138     static void splitVersionedKey(const QByteArray &data, QByteArray &key, int &version);
0139 
0140     /**
0141       Constructs a new IMAP parser.
0142     */
0143     ImapParser();
0144 
0145     /**
0146       Destroys an IMAP parser.
0147     */
0148     ~ImapParser();
0149 
0150     /**
0151       Parses the given line.
0152       @returns True if an IMAP message was parsed completely, false if more data is needed.
0153       @todo read from a QIODevice directly to avoid an extra line buffer
0154     */
0155     bool parseNextLine(const QByteArray &readBuffer);
0156 
0157     /**
0158       Parses the given block of data.
0159       Note: This currently only handles continuation blocks.
0160       @param data The data to parse.
0161     */
0162     void parseBlock(const QByteArray &data);
0163 
0164     /**
0165       Returns the tag of the parsed message.
0166       Only valid if parseNextLine() returned true.
0167     */
0168     QByteArray tag() const;
0169 
0170     /**
0171       Return the raw data of the parsed IMAP message.
0172       Only valid if parseNextLine() returned true.
0173     */
0174     QByteArray data() const;
0175 
0176     /**
0177       Resets the internal state of the parser. Call before parsing
0178       a new IMAP message.
0179     */
0180     void reset();
0181 
0182     /**
0183       Returns true if the last parsed line contained a literal continuation,
0184       ie. readiness for receiving literal data needs to be indicated.
0185     */
0186     bool continuationStarted() const;
0187 
0188     /**
0189       Returns the expected size of liteal data.
0190     */
0191     qint64 continuationSize() const;
0192 
0193 private:
0194     Q_DISABLE_COPY(ImapParser)
0195     std::unique_ptr<ImapParserPrivate> const d;
0196 };
0197 
0198 }