7#include "imapparser_p.h"
16class Akonadi::ImapParserPrivate
27 bool checkLiteralStart(
const QByteArray &readBuffer,
int pos = 0)
39 literalSize = readBuffer.
mid(begin + 1, end - begin - 1).
toLongLong();
42 if (literalSize == 0) {
47 dataBuffer.
reserve(dataBuffer.
size() +
static_cast<int>(literalSize) + 1);
57int parseParenthesizedListHelper(
const QByteArray &data, T &result,
int start)
72 int sublistBegin =
start;
73 bool insideQuote =
false;
74 for (
int i = begin + 1; i < data.
length(); ++i) {
75 const char currentChar = data[i];
76 if (currentChar ==
'(' && !insideQuote) {
85 if (currentChar ==
')' && !insideQuote) {
91 result.append(data.
mid(sublistBegin, i - sublistBegin + 1));
98 if (currentChar ==
' ' || currentChar ==
'\n' || currentChar ==
'\r') {
104 const int consumed = ImapParser::parseString(data, ba, i);
107 }
else if (count > 0) {
108 if (currentChar ==
'"') {
109 insideQuote = !insideQuote;
110 }
else if (currentChar ==
'\\' && insideQuote) {
124 return parseParenthesizedListHelper(data, result,
start);
129 return parseParenthesizedListHelper(data, result,
start);
136 if (begin >= data.
length()) {
142 if (data[begin] ==
'{') {
144 Q_ASSERT(end > begin);
145 int size = data.
mid(begin + 1, end - begin - 1).
toInt();
149 if (begin < data.
length() && data[begin] ==
'\r') {
152 if (begin < data.
length() && data[begin] ==
'\n') {
157 result = data.
mid(begin, end - begin);
162 return parseQuotedString(data, result, begin);
170 if (begin >= data.
length()) {
174 bool foundSlash =
false;
176 if (data[begin] ==
'"') {
179 for (
int i = begin; i < data.
length(); ++i) {
180 const char ch = data.
at(i);
185 }
else if (ch ==
'n') {
187 }
else if (ch ==
'\\') {
189 }
else if (ch ==
'\"') {
209 bool reachedInputEnd =
true;
210 for (
int i = begin; i < data.
length(); ++i) {
211 const char ch = data.
at(i);
212 if (ch ==
' ' || ch ==
'(' || ch ==
')' || ch ==
'\n' || ch ==
'\r') {
214 reachedInputEnd =
false;
221 if (reachedInputEnd) {
224 result = data.
mid(begin, end - begin);
227 if (result ==
"NIL") {
248 if (data[i] !=
' ') {
259 bool insideQuote =
false;
261 const char ch = data[i];
263 insideQuote = !insideQuote;
266 if (ch ==
'\\' && insideQuote) {
270 if (ch ==
'(' && !insideQuote) {
274 if (ch ==
')' && !insideQuote) {
296 for (; it != endIt; ++it) {
297 resultSize += (*it).size();
305 for (; it != endIt; ++it) {
317 return ImapParser::join(list, separator);
323 const int end = parseString(data, tmp,
start);
328int ImapParser::parseNumber(
const QByteArray &data, qint64 &result,
bool *ok,
int start)
334 int pos = stripLeadingSpaces(data,
start);
335 if (pos >= data.
length()) {
340 for (; pos < data.
length(); ++pos) {
341 if (!isdigit(data.
at(pos))) {
359 const int inputLength = data.
length();
360 int stuffToQuote = 0;
361 for (
int i = 0; i < inputLength; ++i) {
362 const char ch = data.
at(i);
363 if (ch ==
'"' || ch ==
'\\' || ch ==
'\n' || ch ==
'\r') {
369 result.
reserve(inputLength + stuffToQuote + 2);
373 if (stuffToQuote == 0) {
376 for (
int i = 0; i < inputLength; ++i) {
377 const char ch = data.
at(i);
388 if (ch ==
'"' || ch ==
'\\') {
400int ImapParser::parseSequenceSet(
const QByteArray &data, ImapSet &result,
int start)
406 for (
int i = begin; i < data.
length(); ++i) {
407 if (data[i] ==
'*') {
409 }
else if (data[i] ==
':') {
411 }
else if (isdigit(data[i])) {
413 i = parseNumber(data, value, &ok, i);
421 result.add(ImapInterval(lower, upper));
425 if (data[i] !=
',') {
436 if (lower >= 0 && upper >= 0) {
437 result.add(ImapInterval(lower, upper));
466 int pos = stripLeadingSpaces(data,
start);
467 if (data.
length() <= pos) {
472 if (data[pos] ==
'"') {
476 if (data.
length() <= pos + 26) {
480 if (data.
length() < pos + 26) {
486 const int day = (data[pos] ==
' ' ? data[pos + 1] -
'0'
487 : data.
mid(pos, 2).toInt(&ok));
493 static const QByteArray shortMonthNames(
"janfebmaraprmayjunjulaugsepoctnovdec");
494 int month = shortMonthNames.indexOf(data.
mid(pos, 3).
toLower());
499 month = month / 3 + 1;
501 const int year = data.
mid(pos, 4).
toInt(&ok);
507 const int hours = data.
mid(pos, 2).
toInt(&ok);
513 const int minutes = data.
mid(pos, 2).
toInt(&ok);
519 const int seconds = data.
mid(pos, 2).
toInt(&ok);
525 const int tzhh = data.
mid(pos, 2).
toInt(&ok);
531 const int tzmm = data.
mid(pos, 2).
toInt(&ok);
536 int tzsecs = tzhh * 60 * 60 + tzmm * 60;
537 if (data[pos - 3] ==
'-') {
541 const QDate date(year, month, day);
542 const QTime time(hours, minutes, seconds);
548 dateTime = dateTime.
addSecs(-tzsecs);
551 if (data.
length() <= pos || !quoted) {
555 if (data[pos] ==
'"') {
564 const int startPos = data.
indexOf(
'[');
565 const int endPos = data.
indexOf(
']');
566 if (startPos != -1 && endPos != -1) {
567 if (endPos > startPos) {
575 key = data.
left(startPos);
583ImapParser::ImapParser()
584 : d(new ImapParserPrivate)
589ImapParser::~ImapParser() =
default;
591bool ImapParser::parseNextLine(
const QByteArray &readBuffer)
593 d->continuation =
false;
596 if (d->tagBuffer.isEmpty()) {
597 const int startOfData = ImapParser::parseString(readBuffer, d->tagBuffer);
598 if (startOfData < readBuffer.
length() && startOfData >= 0) {
599 d->dataBuffer = readBuffer.
mid(startOfData + 1);
603 d->dataBuffer += readBuffer;
607 if (d->literalSize > 0) {
608 d->literalSize -= readBuffer.
size();
611 if (d->literalSize > 0) {
616 if (d->literalSize < 0) {
618 d->parenthesesCount += ImapParser::parenthesesBalance(readBuffer, readBuffer.
length() +
static_cast<int>(d->literalSize));
621 if (d->checkLiteralStart(readBuffer, readBuffer.
length() +
static_cast<int>(d->literalSize))) {
627 if (d->parenthesesCount > 0) {
633 d->parenthesesCount += ImapParser::parenthesesBalance(readBuffer);
636 if (d->checkLiteralStart(readBuffer)) {
641 if (d->parenthesesCount > 0) {
651void ImapParser::parseBlock(
const QByteArray &data)
653 Q_ASSERT(d->literalSize >= data.
size());
654 d->literalSize -= data.
size();
655 d->dataBuffer += data;
665 return d->dataBuffer;
668void ImapParser::reset()
670 d->dataBuffer.
clear();
671 d->tagBuffer.clear();
672 d->parenthesesCount = 0;
674 d->continuation =
false;
677bool ImapParser::continuationStarted()
const
679 return d->continuation;
682qint64 ImapParser::continuationSize()
const
684 return d->literalSize;
Q_SCRIPTABLE Q_NOREPLY void start()
Helper integration between Akonadi and Qt.
KDB_EXPORT KDbVersionInfo version()
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
const QList< QKeySequence > & begin()
char at(qsizetype i) const const
bool contains(QByteArrayView bv) const const
bool endsWith(QByteArrayView bv) const const
qsizetype indexOf(QByteArrayView bv, qsizetype from) const const
bool isEmpty() const const
qsizetype lastIndexOf(QByteArrayView bv) const const
QByteArray left(qsizetype len) const const
qsizetype length() const const
QByteArray mid(qsizetype pos, qsizetype len) const const
QByteArray & replace(QByteArrayView before, QByteArrayView after)
void reserve(qsizetype size)
qsizetype size() const const
int toInt(bool *ok, int base) const const
qlonglong toLongLong(bool *ok, int base) const const
QByteArray toLower() const const
QByteArray trimmed() const const
QDateTime addSecs(qint64 s) const const
bool isValid() const const
const_iterator constBegin() const const
const_iterator constEnd() const const
bool isEmpty() const const
qsizetype size() const const
QString fromUtf8(QByteArrayView str)