From kde-commits Sun May 31 22:59:50 2015 From: =?utf-8?q?Dan_Vr=C3=A1til?= Date: Sun, 31 May 2015 22:59:50 +0000 To: kde-commits Subject: [akonadi/dev/binary-protocol] src: Remove IMAP parsers and clean up #includes Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=143311320602503 Git commit 99b157ee39d0f929dd3bc7d4c58ee25a927219e9 by Dan Vr=C3=A1til. Committed on 31/05/2015 at 22:59. Pushed by dvratil into branch 'dev/binary-protocol'. Remove IMAP parsers and clean up #includes Thanks for your hard work, but we don't need you anymore ;-) M +0 -2 src/private/CMakeLists.txt D +0 -697 src/private/imapparser.cpp D +0 -211 src/private/imapparser_p.h M +8 -7 src/private/imapset.cpp M +9 -3 src/private/notificationmessage.cpp M +9 -10 src/private/notificationmessagev2.cpp M +15 -1 src/private/notificationmessagev2_p_p.h M +0 -1 src/server/CMakeLists.txt M +0 -59 src/server/commandcontext.cpp M +0 -4 src/server/commandcontext.h M +2 -5 src/server/handler.cpp M +0 -3 src/server/handler.h M +2 -13 src/server/handler/akappend.cpp M +0 -4 src/server/handler/akappend.h M +0 -3 src/server/handler/colcopy.cpp M +3 -6 src/server/handler/colmove.cpp M +0 -3 src/server/handler/copy.cpp M +2 -9 src/server/handler/create.cpp M +2 -8 src/server/handler/delete.cpp M +1 -6 src/server/handler/fetch.cpp M +3 -3 src/server/handler/fetchhelper.cpp M +1 -3 src/server/handler/link.cpp M +4 -9 src/server/handler/list.cpp M +0 -2 src/server/handler/login.cpp M +0 -2 src/server/handler/logout.cpp M +5 -12 src/server/handler/modify.cpp M +0 -4 src/server/handler/move.cpp M +3 -5 src/server/handler/relationfetch.cpp M +0 -1 src/server/handler/relationremove.cpp M +1 -4 src/server/handler/relationstore.cpp M +1 -3 src/server/handler/remove.cpp M +0 -4 src/server/handler/resourceselect.cpp M +0 -5 src/server/handler/search.cpp M +2 -1 src/server/handler/searchhelper.cpp M +1 -3 src/server/handler/searchhelper.h M +1 -9 src/server/handler/searchpersistent.cpp M +3 -3 src/server/handler/searchresult.cpp M +1 -11 src/server/handler/select.cpp M +3 -9 src/server/handler/status.cpp M +2 -9 src/server/handler/store.cpp M +0 -3 src/server/handler/store.h M +4 -5 src/server/handler/tagappend.cpp M +0 -4 src/server/handler/tagfetch.cpp M +2 -9 src/server/handler/tagfetchhelper.cpp M +3 -2 src/server/handler/tagremove.cpp M +3 -4 src/server/handler/tagstore.cpp M +1 -5 src/server/handler/transaction.cpp M +2 -51 src/server/handlerhelper.cpp M +1 -15 src/server/handlerhelper.h D +0 -849 src/server/imapstreamparser.cpp D +0 -286 src/server/imapstreamparser.h M +2 -28 src/server/storage/parthelper.cpp M +0 -9 src/server/storage/parthelper.h M +0 -3 src/server/storage/partstreamer.cpp M +1 -0 src/server/storagejanitor.cpp http://commits.kde.org/akonadi/99b157ee39d0f929dd3bc7d4c58ee25a927219e9 diff --git a/src/private/CMakeLists.txt b/src/private/CMakeLists.txt index b3ccf44..6f2d526 100644 --- a/src/private/CMakeLists.txt +++ b/src/private/CMakeLists.txt @@ -1,5 +1,4 @@ set(akonadiprivate_SRCS - imapparser.cpp imapset.cpp notificationmessage.cpp notificationmessagev2.cpp @@ -35,7 +34,6 @@ install(TARGETS = install(FILES ${CMAKE_CURRENT_BINARY_DIR}/akonadiprivate_export.h - imapparser_p.h imapset_p.h notificationmessage_p.h notificationmessagev2_p.h diff --git a/src/private/imapparser.cpp b/src/private/imapparser.cpp deleted file mode 100644 index dc68fe2..0000000 --- a/src/private/imapparser.cpp +++ /dev/null @@ -1,697 +0,0 @@ -/* - Copyright (c) 2006 - 2007 Volker Krause - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published= by - the Free Software Foundation; either version 2 of the License, or (at = your - option) any later version. - - This library is distributed in the hope that it will be useful, but WI= THOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public Lice= nse - along with this library; see the file COPYING.LIB. If not, write to t= he - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Bosto= n, MA - 02110-1301, USA. -*/ - -#include "imapparser_p.h" - -#include -#include - -#include - -using namespace Akonadi; - -class ImapParser::Private -{ -public: - QByteArray tagBuffer; - QByteArray dataBuffer; - int parenthesesCount; - qint64 literalSize; - bool continuation; - - // returns true if readBuffer contains a literal start and sets - // parser state accordingly - bool checkLiteralStart(const QByteArray &readBuffer, int pos =3D 0) - { - if (readBuffer.trimmed().endsWith('}')) { - const int begin =3D readBuffer.lastIndexOf('{'); - const int end =3D readBuffer.lastIndexOf('}'); - - // new literal in previous literal data block - if (begin < pos) { - return false; - } - - // TODO error handling - literalSize =3D readBuffer.mid(begin + 1, end - begin - 1).toL= ongLong(); - - // empty literal - if (literalSize =3D=3D 0) { - return false; - } - - continuation =3D true; - dataBuffer.reserve(dataBuffer.size() + literalSize + 1); - return true; - } - return false; - } -}; - -namespace { - -template -int parseParenthesizedListHelper(const QByteArray &data, T &result, int st= art) -{ - result.clear(); - if (start >=3D data.length()) { - return data.length(); - } - - const int begin =3D data.indexOf('(', start); - if (begin < 0) { - return start; - } - - int count =3D 0; - int sublistBegin =3D start; - bool insideQuote =3D false; - for (int i =3D begin + 1; i < data.length(); ++i) { - const char currentChar =3D data[i]; - if (currentChar =3D=3D '(' && !insideQuote) { - ++count; - if (count =3D=3D 1) { - sublistBegin =3D i; - } - - continue; - } - - if (currentChar =3D=3D ')' && !insideQuote) { - if (count <=3D 0) { - return i + 1; - } - - if (count =3D=3D 1) { - result.append(data.mid(sublistBegin, i - sublistBegin + 1)= ); - } - - --count; - continue; - } - - if (currentChar =3D=3D ' ' || currentChar =3D=3D '\n' || currentCh= ar =3D=3D '\r') { - continue; - } - - if (count =3D=3D 0) { - QByteArray ba; - const int consumed =3D ImapParser::parseString(data, ba, i); - i =3D consumed - 1; // compensate for the for loop increment - result.append(ba); - } else if (count > 0) { - if (currentChar =3D=3D '"') { - insideQuote =3D !insideQuote; - } else if (currentChar =3D=3D '\\' && insideQuote) { - ++i; - continue; - } - } - } - - return data.length(); -} - -} - -int ImapParser::parseParenthesizedList(const QByteArray &data, QVarLengthA= rray &result, int start) -{ - return parseParenthesizedListHelper(data, result, start); -} - -int ImapParser::parseParenthesizedList(const QByteArray &data, QList &result, int start) -{ - return parseParenthesizedListHelper(data, result, start); -} - -int ImapParser::parseString(const QByteArray &data, QByteArray &result, in= t start) -{ - int begin =3D stripLeadingSpaces(data, start); - result.clear(); - if (begin >=3D data.length()) { - return data.length(); - } - - // literal string - // TODO: error handling - if (data[begin] =3D=3D '{') { - int end =3D data.indexOf('}', begin); - Q_ASSERT(end > begin); - int size =3D data.mid(begin + 1, end - begin - 1).toInt(); - - // strip CRLF - begin =3D end + 1; - if (begin < data.length() && data[begin] =3D=3D '\r') { - ++begin; - } - if (begin < data.length() && data[begin] =3D=3D '\n') { - ++begin; - } - - end =3D begin + size; - result =3D data.mid(begin, end - begin); - return end; - } - - // quoted string - return parseQuotedString(data, result, begin); -} - -int ImapParser::parseQuotedString(const QByteArray &data, QByteArray &resu= lt, int start) -{ - int begin =3D stripLeadingSpaces(data, start); - int end =3D begin; - result.clear(); - if (begin >=3D data.length()) { - return data.length(); - } - - bool foundSlash =3D false; - // quoted string - if (data[begin] =3D=3D '"') { - ++begin; - for (int i =3D begin; i < data.length(); ++i) { - const char ch =3D data.at(i); - if (foundSlash) { - foundSlash =3D false; - if (ch =3D=3D 'r') { - result +=3D '\r'; - } else if (ch =3D=3D 'n') { - result +=3D '\n'; - } else if (ch =3D=3D '\\') { - result +=3D '\\'; - } else if (ch =3D=3D '\"') { - result +=3D '\"'; - } else { - //TODO: this is actually an error - result +=3D ch; - } - continue; - } - if (ch =3D=3D '\\') { - foundSlash =3D true; - continue; - } - if (ch =3D=3D '"') { - end =3D i + 1; // skip the '"' - break; - } - result +=3D ch; - } - } else { - // unquoted string - bool reachedInputEnd =3D true; - for (int i =3D begin; i < data.length(); ++i) { - const char ch =3D data.at(i); - if (ch =3D=3D ' ' || ch =3D=3D '(' || ch =3D=3D ')' || ch =3D= =3D '\n' || ch =3D=3D '\r') { - end =3D i; - reachedInputEnd =3D false; - break; - } - if (ch =3D=3D '\\') { - foundSlash =3D true; - } - } - if (reachedInputEnd) { - end =3D data.length(); - } - result =3D data.mid(begin, end - begin); - - // transform unquoted NIL - if (result =3D=3D "NIL") { - result.clear(); - } - - // strip quotes - if (foundSlash) { - while (result.contains("\\\"")) { - result.replace("\\\"", "\""); - } - while (result.contains("\\\\")) { - result.replace("\\\\", "\\"); - } - } - } - - return end; -} - -int ImapParser::stripLeadingSpaces(const QByteArray &data, int start) -{ - for (int i =3D start; i < data.length(); ++i) { - if (data[i] !=3D ' ') { - return i; - } - } - - return data.length(); -} - -int ImapParser::parenthesesBalance(const QByteArray &data, int start) -{ - int count =3D 0; - bool insideQuote =3D false; - for (int i =3D start; i < data.length(); ++i) { - const char ch =3D data[i]; - if (ch =3D=3D '"') { - insideQuote =3D !insideQuote; - continue; - } - if (ch =3D=3D '\\' && insideQuote) { - ++i; - continue; - } - if (ch =3D=3D '(' && !insideQuote) { - ++count; - continue; - } - if (ch =3D=3D ')' && !insideQuote) { - --count; - continue; - } - } - return count; -} - -QByteArray ImapParser::join(const QList &list, const QByteArra= y &separator) -{ - // shortcuts for the easy cases - if (list.isEmpty()) { - return QByteArray(); - } - if (list.size() =3D=3D 1) { - return list.first(); - } - - // avoid expensive realloc's by determining the size beforehand - QList::const_iterator it =3D list.constBegin(); - const QList::const_iterator endIt =3D list.constEnd(); - int resultSize =3D (list.size() - 1) * separator.size(); - for (; it !=3D endIt; ++it) { - resultSize +=3D (*it).size(); - } - - QByteArray result; - result.reserve(resultSize); - it =3D list.constBegin(); - result +=3D (*it); - ++it; - for (; it !=3D endIt; ++it) { - result +=3D separator; - result +=3D (*it); - } - - return result; -} - -QByteArray ImapParser::join(const QSet &set, const QByteArray = &separator) -{ - const QList list =3D QList::fromSet(set); - - return ImapParser::join(list, separator); -} - -int ImapParser::parseString(const QByteArray &data, QString &result, int s= tart) -{ - QByteArray tmp; - const int end =3D parseString(data, tmp, start); - result =3D QString::fromUtf8(tmp); - return end; -} - -int ImapParser::parseNumber(const QByteArray &data, qint64 &result, bool *= ok, int start) -{ - if (ok) { - *ok =3D false; - } - - int pos =3D stripLeadingSpaces(data, start); - if (pos >=3D data.length()) { - return data.length(); - } - - int begin =3D pos; - for (; pos < data.length(); ++pos) { - if (!isdigit(data.at(pos))) { - break; - } - } - - const QByteArray tmp =3D data.mid(begin, pos - begin); - result =3D tmp.toLongLong(ok); - - return pos; -} - -QByteArray ImapParser::quote(const QByteArray &data) -{ - if (data.isEmpty()) { - static const QByteArray empty("\"\""); - return empty; - } - - const int inputLength =3D data.length(); - int stuffToQuote =3D 0; - for (int i =3D 0; i < inputLength; ++i) { - const char ch =3D data.at(i); - if (ch =3D=3D '"' || ch =3D=3D '\\' || ch =3D=3D '\n' || ch =3D=3D= '\r') { - ++stuffToQuote; - } - } - - QByteArray result; - result.reserve(inputLength + stuffToQuote + 2); - result +=3D '"'; - - // shortcut for the case that we don't need to quote anything at all - if (stuffToQuote =3D=3D 0) { - result +=3D data; - } else { - for (int i =3D 0; i < inputLength; ++i) { - const char ch =3D data.at(i); - if (ch =3D=3D '\n') { - result +=3D "\\n"; - continue; - } - - if (ch =3D=3D '\r') { - result +=3D "\\r"; - continue; - } - - if (ch =3D=3D '"' || ch =3D=3D '\\') { - result +=3D '\\'; - } - - result +=3D ch; - } - } - - result +=3D '"'; - return result; -} - -int ImapParser::parseSequenceSet(const QByteArray &data, ImapSet &result, = int start) -{ - int begin =3D stripLeadingSpaces(data, start); - qint64 value =3D -1, lower =3D -1, upper =3D -1; - for (int i =3D begin; i < data.length(); ++i) { - if (data[i] =3D=3D '*') { - value =3D 0; - } else if (data[i] =3D=3D ':') { - lower =3D value; - } else if (isdigit(data[i])) { - bool ok =3D false; - i =3D parseNumber(data, value, &ok, i); - Q_ASSERT(ok); // TODO handle error - --i; - } else { - upper =3D value; - if (lower < 0) { - lower =3D value; - } - result.add(ImapInterval(lower, upper)); - lower =3D -1; - upper =3D -1; - value =3D -1; - if (data[i] !=3D ',') { - return i; - } - } - } - // take care of left-overs at input end - upper =3D value; - if (lower < 0) { - lower =3D value; - } - - if (lower >=3D 0 && upper >=3D 0) { - result.add(ImapInterval(lower, upper)); - } - - return data.length(); -} - -int ImapParser::parseDateTime(const QByteArray &data, QDateTime &dateTime,= int start) -{ - // Syntax: - // date-time =3D DQUOTE date-day-fixed "-" date-month "-" date-ye= ar - // SP time SP zone DQUOTE - // date-day-fixed =3D (SP DIGIT) / 2DIGIT - // ; Fixed-format version of date-day - // date-month =3D "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / - // "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" - // date-year =3D 4DIGIT - // time =3D 2DIGIT ":" 2DIGIT ":" 2DIGIT - // ; Hours minutes seconds - // zone =3D ("+" / "-") 4DIGIT - // ; Signed four-digit value of hhmm representing - // ; hours and minutes east of Greenwich (that is, - // ; the amount that the given time differs from - // ; Universal Time). Subtracting the timezone - // ; from the given time will give the UT form. - // ; The Universal Time zone is "+0000". - // Example : "28-May-2006 01:03:35 +0200" - // Position: 0123456789012345678901234567 - // 1 2 - - int pos =3D stripLeadingSpaces(data, start); - if (data.length() <=3D pos) { - return pos; - } - - bool quoted =3D false; - if (data[pos] =3D=3D '"') { - quoted =3D true; - ++pos; - - if (data.length() <=3D pos + 26) { - return start; - } - } else { - if (data.length() < pos + 26) { - return start; - } - } - - bool ok =3D true; - const int day =3D (data[pos] =3D=3D ' ' ? data[pos + 1] - '0' // sing= le digit day - : data.mid(pos, 2).toInt(&ok)); - if (!ok) { - return start; - } - - pos +=3D 3; - static const QByteArray shortMonthNames("janfebmaraprmayjunjulaugsepoc= tnovdec"); - int month =3D shortMonthNames.indexOf(data.mid(pos, 3).toLower()); - if (month =3D=3D -1) { - return start; - } - - month =3D month / 3 + 1; - pos +=3D 4; - const int year =3D data.mid(pos, 4).toInt(&ok); - if (!ok) { - return start; - } - - pos +=3D 5; - const int hours =3D data.mid(pos, 2).toInt(&ok); - if (!ok) { - return start; - } - - pos +=3D 3; - const int minutes =3D data.mid(pos, 2).toInt(&ok); - if (!ok) { - return start; - } - - pos +=3D 3; - const int seconds =3D data.mid(pos, 2).toInt(&ok); - if (!ok) { - return start; - } - - pos +=3D 4; - const int tzhh =3D data.mid(pos, 2).toInt(&ok); - if (!ok) { - return start; - } - - pos +=3D 2; - const int tzmm =3D data.mid(pos, 2).toInt(&ok); - if (!ok) { - return start; - } - - int tzsecs =3D tzhh * 60 * 60 + tzmm * 60; - if (data[pos - 3] =3D=3D '-') { - tzsecs =3D -tzsecs; - } - - const QDate date(year, month, day); - const QTime time(hours, minutes, seconds); - dateTime =3D QDateTime(date, time, Qt::UTC); - if (!dateTime.isValid()) { - return start; - } - - dateTime =3D dateTime.addSecs(-tzsecs); - - pos +=3D 2; - if (data.length() <=3D pos || !quoted) { - return pos; - } - - if (data[pos] =3D=3D '"') { - ++pos; - } - - return pos; -} - -void ImapParser::splitVersionedKey(const QByteArray &data, QByteArray &key= , int &version) -{ - if (data.contains('[') && data.contains(']')) { - const int startPos =3D data.indexOf('['); - const int endPos =3D data.indexOf(']'); - if (startPos !=3D -1 && endPos !=3D -1 && endPos > startPos) { - bool ok =3D false; - - version =3D data.mid(startPos + 1, endPos - startPos - 1).toIn= t(&ok); - if (!ok) { - version =3D 0; - } - - key =3D data.left(startPos); - } - } else { - key =3D data; - version =3D 0; - } -} - -ImapParser::ImapParser() - : d(new Private) -{ - reset(); -} - -ImapParser::~ImapParser() -{ - delete d; -} - -bool ImapParser::parseNextLine(const QByteArray &readBuffer) -{ - d->continuation =3D false; - - // first line, get the tag - if (d->tagBuffer.isEmpty()) { - const int startOfData =3D ImapParser::parseString(readBuffer, d->t= agBuffer); - if (startOfData < readBuffer.length() && startOfData >=3D 0) { - d->dataBuffer =3D readBuffer.mid(startOfData + 1); - } - - } else { - d->dataBuffer +=3D readBuffer; - } - - // literal read in progress - if (d->literalSize > 0) { - d->literalSize -=3D readBuffer.size(); - - // still not everything read - if (d->literalSize > 0) { - return false; - } - - // check the remaining (non-literal) part for parentheses - if (d->literalSize < 0) { - // the following looks strange but works since literalSize can= be negative here - d->parenthesesCount +=3D ImapParser::parenthesesBalance(readBu= ffer, readBuffer.length() + d->literalSize); - - // check if another literal read was started - if (d->checkLiteralStart(readBuffer, readBuffer.length() + d->= literalSize)) { - return false; - } - } - - // literal string finished but still open parentheses - if (d->parenthesesCount > 0) { - return false; - } - - } else { - - // open parentheses - d->parenthesesCount +=3D ImapParser::parenthesesBalance(readBuffer= ); - - // start new literal read - if (d->checkLiteralStart(readBuffer)) { - return false; - } - - // still open parentheses - if (d->parenthesesCount > 0) { - return false; - } - - // just a normal response, fall through - } - - return true; -} - -void ImapParser::parseBlock(const QByteArray &data) -{ - Q_ASSERT(d->literalSize >=3D data.size()); - d->literalSize -=3D data.size(); - d->dataBuffer +=3D data; -} - -QByteArray ImapParser::tag() const -{ - return d->tagBuffer; -} - -QByteArray ImapParser::data() const -{ - return d->dataBuffer; -} - -void ImapParser::reset() -{ - d->dataBuffer.clear(); - d->tagBuffer.clear(); - d->parenthesesCount =3D 0; - d->literalSize =3D 0; - d->continuation =3D false; -} - -bool ImapParser::continuationStarted() const -{ - return d->continuation; -} - -qint64 ImapParser::continuationSize() const -{ - return d->literalSize; -} diff --git a/src/private/imapparser_p.h b/src/private/imapparser_p.h deleted file mode 100644 index 88add05..0000000 --- a/src/private/imapparser_p.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - Copyright (c) 2006 - 2007 Volker Krause - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published= by - the Free Software Foundation; either version 2 of the License, or (at = your - option) any later version. - - This library is distributed in the hope that it will be useful, but WI= THOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public Lice= nse - along with this library; see the file COPYING.LIB. If not, write to t= he - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Bosto= n, MA - 02110-1301, USA. -*/ - -#ifndef AKONADI_IMAPPARSER_P_H -#define AKONADI_IMAPPARSER_P_H - -#include "akonadiprivate_export.h" - -#include "imapset_p.h" - -#include -#include -#include - -namespace Akonadi { - -/** - Parser for IMAP messages. -*/ -class AKONADIPRIVATE_EXPORT ImapParser -{ -public: - /** - Parses the next parenthesized list in @p data starting from @p start - and puts the result into @p result. The number of used characters is - returned. - This does not recurse into sub-lists. - @param data Source data. - @param result The parsed list. - @param start Start parsing at this index. - */ - static int parseParenthesizedList(const QByteArray &data, QList &result, int start =3D 0); - static int parseParenthesizedList(const QByteArray &data, QVarLengthAr= ray &result, int start =3D 0); - - /** - Parse the next string in @p data (quoted or literal) starting from @= p start - and puts the result into @p result. The number of used characters is= returned - (this is not equal to result.length()!). - @param data Source data. - @param result Parsed string, quotation, literal marker, etc. are rem= oved, - 'NIL' is transformed into an empty QByteArray. - @param start start parsing at this index. - */ - static int parseString(const QByteArray &data, QByteArray &result, int= start =3D 0); - - /** - Parses the next quoted string from @p data starting at @p start and = puts it into - @p result. The number of parsed characters is returned (this is not = equal to result.length()!). - @param data Source data. - @param result Parsed string, quotation is removed and 'NIL' is trans= formed to an empty QByteArray. - @param start Start parsing at this index. - */ - static int parseQuotedString(const QByteArray &data, QByteArray &resul= t, int start =3D 0); - - /** - Returns the number of leading espaces in @p data starting from @p st= art. - @param data The source data. - @param start Start parsing at this index. - */ - static int stripLeadingSpaces(const QByteArray &data, int start =3D 0); - - /** - Returns the parentheses balance for the given data, considering quot= es. - @param data The source data. - @param start Start parsing at this index. - */ - static int parenthesesBalance(const QByteArray &data, int start =3D 0); - - /** - Joins a QByteArray list with the given separator. - @param list The QByteArray list to join. - @param separator The separator. - */ - static QByteArray join(const QList &list, const QByteArray= &separator); - - /** - Joins a QByteArray set with the given separator. - @param set The QByteArray set to join. - @param separator The separator. - */ - static QByteArray join(const QSet &set, const QByteArray &= separator); - - /** - Same as parseString(), but with additional UTF-8 decoding of the res= ult. - @param data Source data. - @param result Parsed string, quotation, literal marker, etc. are rem= oved, - 'NIL' is transformed into an empty QString. UTF-8 decoding is applie= d.. - @param start Start parsing at this index. - */ - static int parseString(const QByteArray &data, QString &result, int st= art =3D 0); - - /** - Parses the next integer number from @p data starting at start and pu= ts it into - @p result. The number of characters parsed is returned (this is not = the parsed result!). - @param data Source data. - @param result Parsed integer number, invalid if ok is false. - @param ok Set to false if the parsing failed. - @param start Start parsing at this index. - */ - static int parseNumber(const QByteArray &data, qint64 &result, bool *o= k =3D 0, int start =3D 0); - - /** - Quotes the given QByteArray. - @param data Source data. - */ - static QByteArray quote(const QByteArray &data); - - /** - Parse an IMAP sequence set. - @param data source data. - @param result The parse sequence set. - @param start start parsing at this index. - @return end position of parsing. - */ - static int parseSequenceSet(const QByteArray &data, ImapSet &result, i= nt start =3D 0); - - /** - Parse an IMAP date/time value. - @param data source data. - @param dateTime The result date/time. - @param start Start parsing at this index. - @return end position of parsing. - */ - static int parseDateTime(const QByteArray &data, QDateTime &dateTime, = int start =3D 0); - - /** - Split a versioned key of the form 'key[version]' into its components. - @param data The versioned key. - @param key The unversioned key. - @param version The version of the key or 0 if no version was set. - */ - static void splitVersionedKey(const QByteArray &data, QByteArray &key,= int &version); - - /** - Constructs a new IMAP parser. - */ - ImapParser(); - - /** - Destroys an IMAP parser. - */ - ~ImapParser(); - - /** - Parses the given line. - @returns True if an IMAP message was parsed completely, false if mor= e data is needed. - @todo read from a QIODevice directly to avoid an extra line buffer - */ - bool parseNextLine(const QByteArray &readBuffer); - - /** - Parses the given block of data. - Note: This currently only handles continuation blocks. - @param data The data to parse. - */ - void parseBlock(const QByteArray &data); - - /** - Returns the tag of the parsed message. - Only valid if parseNextLine() returned true. - */ - QByteArray tag() const; - - /** - Return the raw data of the parsed IMAP message. - Only valid if parseNextLine() returned true. - */ - QByteArray data() const; - - /** - Resets the internal state of the parser. Call before parsing - a new IMAP message. - */ - void reset(); - - /** - Returns true if the last parsed line contained a literal continuatio= n, - ie. readiness for receiving literal data needs to be indicated. - */ - bool continuationStarted() const; - - /** - Returns the expected size of liteal data. - */ - qint64 continuationSize() const; - -private: - Q_DISABLE_COPY(ImapParser) - class Private; - Private *const d; -}; - -} - -#endif diff --git a/src/private/imapset.cpp b/src/private/imapset.cpp index e1c0426..761f75d 100644 --- a/src/private/imapset.cpp +++ b/src/private/imapset.cpp @@ -19,9 +19,7 @@ = #include "imapset_p.h" = -#include "imapparser_p.h" - -#include +#include #include = #include @@ -239,12 +237,15 @@ void ImapSet::add(const ImapInterval &interval) = QByteArray ImapSet::toImapSequenceSet() const { - QList rv; - Q_FOREACH (const ImapInterval &interval, d->intervals) { - rv << interval.toImapSequence(); + QByteArray rv; + for (auto iter =3D d->intervals.cbegin(), end =3D d->intervals.cend();= iter !=3D end; ++iter) { + if (iter !=3D d->intervals.cbegin()) { + rv +=3D ","; + } + rv +=3D iter->toImapSequence(); } = - return ImapParser::join(rv, ","); + return rv; } = ImapInterval::List ImapSet::intervals() const diff --git a/src/private/notificationmessage.cpp b/src/private/notification= message.cpp index 9a55ce0..42d8115 100644 --- a/src/private/notificationmessage.cpp +++ b/src/private/notificationmessage.cpp @@ -18,7 +18,6 @@ */ = #include "notificationmessage_p.h" -#include "imapparser_p.h" = #include #include @@ -278,11 +277,18 @@ QString NotificationMessage::toString() const case Add: rv +=3D QLatin1String("added"); break; - case Modify: + case Modify: { rv +=3D QLatin1String("modified parts ("); - rv +=3D QString::fromLatin1(ImapParser::join(itemParts().toList(),= ", ")); + QSet parts =3D itemParts(); + for (auto iter =3D parts.cbegin(), end =3D parts.cend(); iter !=3D= end; ++iter) { + if (iter !=3D parts.cbegin()) { + rv +=3D QLatin1String(", "); + } + rv +=3D QString::fromLatin1(*iter); + } rv +=3D QLatin1String(")"); break; + } case Move: rv +=3D QLatin1String("moved"); break; diff --git a/src/private/notificationmessagev2.cpp b/src/private/notificati= onmessagev2.cpp index 15260eb..9b9713b 100644 --- a/src/private/notificationmessagev2.cpp +++ b/src/private/notificationmessagev2.cpp @@ -21,12 +21,11 @@ #include "notificationmessagev2_p.h" #include "notificationmessagev2_p_p.h" #include "notificationmessage_p.h" -#include "imapparser_p.h" = #include #include #include -#include +#include = using namespace Akonadi; = @@ -274,7 +273,7 @@ QString NotificationMessageV2::toString() const itemStr +=3D QLatin1String(")"); items << itemStr.toLatin1(); } - rv +=3D QLatin1String("(") + QString::fromLatin1(ImapParser::join(item= s, ", ")) + QLatin1String(")"); + rv +=3D QLatin1String("(") + QString::fromLatin1(NotificationMessageHe= lpers::join(items, ", ")) + QLatin1String(")"); = if (d->parentDestCollection >=3D 0) { rv +=3D QLatin1String(" from "); @@ -294,16 +293,16 @@ QString NotificationMessageV2::toString() const break; case Modify: rv +=3D QLatin1String("modified parts ("); - rv +=3D QString::fromLatin1(ImapParser::join(d->parts.toList(), ",= ")); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(d->pa= rts, ", ")); rv +=3D QLatin1String(")"); break; case ModifyFlags: rv +=3D QLatin1String("added flags ("); - rv +=3D QString::fromLatin1(ImapParser::join(d->addedFlags.toList(= ), ", ")); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(d->ad= dedFlags, ", ")); rv +=3D QLatin1String(") "); = rv +=3D QLatin1String("removed flags ("); - rv +=3D QString::fromLatin1(ImapParser::join(d->removedFlags.toLis= t(), ", ")); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(d->re= movedFlags, ", ")); rv +=3D QLatin1String(") "); break; case ModifyTags: { @@ -312,7 +311,7 @@ QString NotificationMessageV2::toString() const Q_FOREACH (qint64 tagId, d->addedTags) { tags << QByteArray::number(tagId); } - rv +=3D QString::fromLatin1(ImapParser::join(tags, ", ")); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(t= ags, ", ")); rv +=3D QLatin1String(") "); = tags.clear(); @@ -320,17 +319,17 @@ QString NotificationMessageV2::toString() const tags << QByteArray::number(tagId); } rv +=3D QLatin1String("removed tags ("); - rv +=3D QString::fromLatin1(ImapParser::join(tags, ", ")); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(t= ags, ", ")); rv +=3D QLatin1String(") "); break; } case ModifyRelations: { rv +=3D QLatin1String( "added relations (" ); - rv +=3D QString::fromLatin1( ImapParser::join( d->addedFlags.t= oList(), ", " ) ); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(d= ->addedFlags, ", ")); rv +=3D QLatin1String( ") " ); = rv +=3D QLatin1String( "removed relations (" ); - rv +=3D QString::fromLatin1( ImapParser::join( d->removedFlags= .toList(), ", " ) ); + rv +=3D QString::fromLatin1(NotificationMessageHelpers::join(d= ->removedFlags, ", ")); rv +=3D QLatin1String( ") " ); break; } diff --git a/src/private/notificationmessagev2_p_p.h b/src/private/notifica= tionmessagev2_p_p.h index 138cdfe..5337651 100644 --- a/src/private/notificationmessagev2_p_p.h +++ b/src/private/notificationmessagev2_p_p.h @@ -126,8 +126,22 @@ public: list.append(msg); return true; } + + template class Container> + static QByteArray join(const Container &v, const QByteArra= y &separator) + { + QByteArray rv; + for (auto iter =3D v.cbegin(), end =3D v.cend(); iter !=3D end; ++= iter) { + if (iter !=3D v.cbegin()) { + rv +=3D separator; + } + rv +=3D (*iter); + } + return rv; + } + }; = -} +} // namespace Akonadi = #endif diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 109fa78..df874ca 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -134,7 +134,6 @@ set(libakonadiserver_SRCS resourcemanager.cpp cachecleaner.cpp debuginterface.cpp - imapstreamparser.cpp preprocessorinstance.cpp preprocessormanager.cpp storagejanitor.cpp diff --git a/src/server/commandcontext.cpp b/src/server/commandcontext.cpp index 44dbec1..e509d54 100644 --- a/src/server/commandcontext.cpp +++ b/src/server/commandcontext.cpp @@ -18,11 +18,6 @@ */ = #include "commandcontext.h" -#include "imapstreamparser.h" -#include "handler.h" -#include "storage/selectquerybuilder.h" - -#include = using namespace Akonadi::Server; = @@ -83,57 +78,3 @@ bool CommandContext::isEmpty() const { return !mCollection.isValid() && mTagId < 0; } - -void CommandContext::parseContext(ImapStreamParser *parser) -{ - // Context - if (!parser->hasString()) { - return; - } - - const QByteArray param =3D parser->peekString(); - - if (param =3D=3D AKONADI_PARAM_COLLECTIONID) { - parser->readString(); // Read the param - bool ok =3D false; - const qint64 colId =3D parser->readNumber(&ok); - if (!ok) { - throw HandlerException("Invalid FETCH collection ID"); - } - const Collection col =3D Collection::retrieveById(colId); - if (!col.isValid()) { - throw HandlerException("No such collection"); - } - setCollection(col); - } else if (param =3D=3D AKONADI_PARAM_COLLECTION) { - if (!resource().isValid()) { - throw HandlerException("Only resources can use REMOTEID"); - } - parser->readString(); // Read the param - const QByteArray rid =3D parser->readString(); - SelectQueryBuilder qb; - qb.addValueCondition(Collection::remoteIdColumn(), Query::Equals, = QString::fromUtf8(rid)); - qb.addValueCondition(Collection::resourceIdColumn(), Query::Equals= , resource().id()); - if (!qb.exec()) { - throw HandlerException("Failed to select collection"); - } - Collection::List results =3D qb.result(); - if (results.count() !=3D 1) { - throw HandlerException(QByteArray::number(results.count()) + "= collections found"); - } - setCollection(results.first()); - } - - if (param =3D=3D AKONADI_PARAM_TAGID) { - parser->readString(); // Read the param - bool ok =3D false; - const qint64 tagId =3D parser->readNumber(&ok); - if (!ok) { - throw HandlerException("Invalid FETCH tag"); - } - if (!Tag::exists(tagId)) { - throw HandlerException("No such tag"); - } - setTag(tagId); - } -} diff --git a/src/server/commandcontext.h b/src/server/commandcontext.h index 3490b1b..62869af 100644 --- a/src/server/commandcontext.h +++ b/src/server/commandcontext.h @@ -25,8 +25,6 @@ namespace Akonadi { namespace Server { = -class ImapStreamParser; - class CommandContext { public: @@ -46,8 +44,6 @@ public: = bool isEmpty() const; = - void parseContext(ImapStreamParser *parser); - private: Resource mResource; Collection mCollection; diff --git a/src/server/handler.cpp b/src/server/handler.cpp index 360535c..7b181d3 100644 --- a/src/server/handler.cpp +++ b/src/server/handler.cpp @@ -18,10 +18,7 @@ *************************************************************************= **/ #include "handler.h" = -#include -#include - -#include +#include #include = #include "connection.h" @@ -57,7 +54,7 @@ #include "handler/relationfetch.h" = #include "storage/querybuilder.h" -#include "imapstreamparser.h" + = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler.h b/src/server/handler.h index 12535b3..49d5a16 100644 --- a/src/server/handler.h +++ b/src/server/handler.h @@ -19,10 +19,7 @@ #ifndef AKONADIHANDLER_H #define AKONADIHANDLER_H = -#include -#include #include -#include #include = #include "global.h" diff --git a/src/server/handler/akappend.cpp b/src/server/handler/akappend.= cpp index 0561354..508d16a 100644 --- a/src/server/handler/akappend.cpp +++ b/src/server/handler/akappend.cpp @@ -18,21 +18,12 @@ *************************************************************************= **/ = #include "akappend.h" -#include "fetchhelper.h" - -#include -#include - -#include "imapstreamparser.h" - -#include "response.h" -#include "handlerhelper.h" = -#include "akonadi.h" +#include "fetchhelper.h" #include "connection.h" #include "preprocessormanager.h" +#include "handlerhelper.h" #include "storage/datastore.h" -#include "storage/entity.h" #include "storage/transaction.h" #include "storage/parttypehelper.h" #include "storage/dbconfig.h" @@ -40,8 +31,6 @@ #include "storage/parthelper.h" #include "storage/selectquerybuilder.h" = -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/akappend.h b/src/server/handler/akappend.h index a10c611..81a0c10 100644 --- a/src/server/handler/akappend.h +++ b/src/server/handler/akappend.h @@ -22,10 +22,6 @@ #include "handler.h" #include "entities.h" = -#include -#include - -class QTemporaryFile; namespace Akonadi { namespace Server { = diff --git a/src/server/handler/colcopy.cpp b/src/server/handler/colcopy.cpp index f198a6e..66a5e96 100644 --- a/src/server/handler/colcopy.cpp +++ b/src/server/handler/colcopy.cpp @@ -19,8 +19,6 @@ = #include "colcopy.h" = -#include - #include "connection.h" #include "handlerhelper.h" #include "cachecleaner.h" @@ -28,7 +26,6 @@ #include "storage/transaction.h" #include "storage/itemretriever.h" #include "storage/collectionqueryhelper.h" -#include "imapstreamparser.h" = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/colmove.cpp b/src/server/handler/colmove.cpp index b72019f..5725e27 100644 --- a/src/server/handler/colmove.cpp +++ b/src/server/handler/colmove.cpp @@ -18,18 +18,15 @@ */ = #include "colmove.h" + #include "handlerhelper.h" -#include "storage/datastore.h" #include "connection.h" +#include "cachecleaner.h" +#include "storage/datastore.h" #include "storage/itemretriever.h" -#include "imapstreamparser.h" #include "storage/transaction.h" #include "storage/collectionqueryhelper.h" #include "storage/selectquerybuilder.h" -#include "cachecleaner.h" - -#include -#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/copy.cpp b/src/server/handler/copy.cpp index 2e99ad7..378621e 100644 --- a/src/server/handler/copy.cpp +++ b/src/server/handler/copy.cpp @@ -22,8 +22,6 @@ #include "connection.h" #include "handlerhelper.h" #include "cachecleaner.h" -#include "imapstreamparser.h" - #include "storage/datastore.h" #include "storage/itemqueryhelper.h" #include "storage/itemretriever.h" @@ -32,7 +30,6 @@ #include "storage/parthelper.h" = #include -#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/create.cpp b/src/server/handler/create.cpp index 194830f..c36615a 100644 --- a/src/server/handler/create.cpp +++ b/src/server/handler/create.cpp @@ -18,20 +18,13 @@ *************************************************************************= **/ #include "create.h" = -#include -#include - #include "connection.h" +#include "handlerhelper.h" #include "storage/datastore.h" -#include "storage/entity.h" #include "storage/transaction.h" -#include "handlerhelper.h" #include "storage/selectquerybuilder.h" -#include "response.h" -#include "imapstreamparser.h" = -#include -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/delete.cpp b/src/server/handler/delete.cpp index 9f77360..3f0aaeb 100644 --- a/src/server/handler/delete.cpp +++ b/src/server/handler/delete.cpp @@ -21,19 +21,13 @@ = #include "connection.h" #include "handlerhelper.h" -#include "response.h" #include "storage/datastore.h" -#include "storage/entity.h" #include "storage/transaction.h" -#include "search/searchmanager.h" -#include "imapstreamparser.h" #include "storage/selectquerybuilder.h" #include "storage/collectionqueryhelper.h" +#include "search/searchmanager.h" = -#include -#include - -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/fetch.cpp b/src/server/handler/fetch.cpp index 5c05c03..d01ca88 100644 --- a/src/server/handler/fetch.cpp +++ b/src/server/handler/fetch.cpp @@ -19,15 +19,10 @@ = #include "fetch.h" = -#include "akonadi.h" #include "connection.h" #include "fetchhelper.h" -#include "response.h" -#include "storage/selectquerybuilder.h" -#include "imapstreamparser.h" #include "cachecleaner.h" - -#include +#include "storage/selectquerybuilder.h" = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/fetchhelper.cpp b/src/server/handler/fetchh= elper.cpp index 2207ddc..f9419c0 100644 --- a/src/server/handler/fetchhelper.cpp +++ b/src/server/handler/fetchhelper.cpp @@ -23,7 +23,6 @@ #include "connection.h" #include "handler.h" #include "handlerhelper.h" -#include "response.h" #include "storage/selectquerybuilder.h" #include "storage/itemqueryhelper.h" #include "storage/itemretrievalmanager.h" @@ -37,10 +36,11 @@ #include "dbusconnectionpool.h" #include "tagfetchhelper.h" #include "relationfetch.h" + +#include + #include #include -#include -#include = #include #include diff --git a/src/server/handler/link.cpp b/src/server/handler/link.cpp index b806c45..6c14db8 100644 --- a/src/server/handler/link.cpp +++ b/src/server/handler/link.cpp @@ -26,10 +26,8 @@ #include "storage/transaction.h" #include "storage/selectquerybuilder.h" #include "storage/collectionqueryhelper.h" -#include "entities.h" -#include "imapstreamparser.h" = -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/list.cpp b/src/server/handler/list.cpp index 0650814..5219500 100644 --- a/src/server/handler/list.cpp +++ b/src/server/handler/list.cpp @@ -19,20 +19,15 @@ = #include "list.h" #include "akonadiserver_debug.h" -#include - -#include "storage/datastore.h" -#include "storage/entity.h" -#include "storage/selectquerybuilder.h" -#include "storage/collectionqueryhelper.h" = #include "connection.h" -#include "response.h" #include "handlerhelper.h" -#include "imapstreamparser.h" #include "collectionreferencemanager.h" +#include "storage/datastore.h" +#include "storage/selectquerybuilder.h" +#include "storage/collectionqueryhelper.h" = -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/login.cpp b/src/server/handler/login.cpp index d588384..e003d3e 100644 --- a/src/server/handler/login.cpp +++ b/src/server/handler/login.cpp @@ -21,8 +21,6 @@ = #include "connection.h" = -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/logout.cpp b/src/server/handler/logout.cpp index 6e933c8..e7b567f 100644 --- a/src/server/handler/logout.cpp +++ b/src/server/handler/logout.cpp @@ -19,8 +19,6 @@ = #include "logout.h" = -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/modify.cpp b/src/server/handler/modify.cpp index 7ff81d9..03d491c 100644 --- a/src/server/handler/modify.cpp +++ b/src/server/handler/modify.cpp @@ -19,25 +19,18 @@ = #include "modify.h" = +#include "akonadi.h" #include "connection.h" +#include "handlerhelper.h" +#include "cachecleaner.h" +#include "collectionreferencemanager.h" +#include "intervalcheck.h" #include "storage/datastore.h" -#include "storage/entity.h" #include "storage/transaction.h" -#include "imapstreamparser.h" -#include "handlerhelper.h" -#include "response.h" #include "storage/itemretriever.h" #include "storage/selectquerybuilder.h" #include "storage/collectionqueryhelper.h" #include "search/searchmanager.h" -#include "cachecleaner.h" -#include "collectionreferencemanager.h" -#include "akonadi.h" -#include "intervalcheck.h" - -#include -#include -#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/move.cpp b/src/server/handler/move.cpp index 7bb5499..9dcd9a2 100644 --- a/src/server/handler/move.cpp +++ b/src/server/handler/move.cpp @@ -20,8 +20,6 @@ #include "move.h" = #include "connection.h" -#include "entities.h" -#include "imapstreamparser.h" #include "handlerhelper.h" #include "cachecleaner.h" #include "storage/datastore.h" @@ -31,8 +29,6 @@ #include "storage/transaction.h" #include "storage/collectionqueryhelper.h" = -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/relationfetch.cpp b/src/server/handler/rela= tionfetch.cpp index 97343e6..2c2a86a 100644 --- a/src/server/handler/relationfetch.cpp +++ b/src/server/handler/relationfetch.cpp @@ -18,14 +18,12 @@ *************************************************************************= **/ = #include "relationfetch.h" -#include "imapstreamparser.h" + #include "connection.h" -#include "response.h" -#include -#include -#include #include "storage/selectquerybuilder.h" = +#include + using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/relationremove.cpp b/src/server/handler/rel= ationremove.cpp index 89c0d16..be81a3f 100644 --- a/src/server/handler/relationremove.cpp +++ b/src/server/handler/relationremove.cpp @@ -24,7 +24,6 @@ #include "storage/selectquerybuilder.h" #include "storage/queryhelper.h" #include "storage/datastore.h" -#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/relationstore.cpp b/src/server/handler/rela= tionstore.cpp index 9b1b01e..10391cf 100644 --- a/src/server/handler/relationstore.cpp +++ b/src/server/handler/relationstore.cpp @@ -18,14 +18,11 @@ */ = #include "relationstore.h" + #include "connection.h" -#include "imapstreamparser.h" -#include "response.h" #include "storage/datastore.h" #include "storage/querybuilder.h" #include "storage/selectquerybuilder.h" -#include "entities.h" -#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/remove.cpp b/src/server/handler/remove.cpp index 11c12aa..f0e8265 100644 --- a/src/server/handler/remove.cpp +++ b/src/server/handler/remove.cpp @@ -20,14 +20,12 @@ #include "remove.h" = #include "connection.h" -#include "entities.h" -#include "imapstreamparser.h" #include "storage/datastore.h" #include "storage/itemqueryhelper.h" #include "storage/selectquerybuilder.h" #include "storage/transaction.h" = -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/resourceselect.cpp b/src/server/handler/res= ourceselect.cpp index 517200c..d8825f3 100644 --- a/src/server/handler/resourceselect.cpp +++ b/src/server/handler/resourceselect.cpp @@ -20,10 +20,6 @@ #include "resourceselect.h" = #include "connection.h" -#include "entities.h" -#include "imapstreamparser.h" - -#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/search.cpp b/src/server/handler/search.cpp index baa044d..99c8d76 100644 --- a/src/server/handler/search.cpp +++ b/src/server/handler/search.cpp @@ -19,18 +19,13 @@ = #include "search.h" = -#include "akonadi.h" #include "connection.h" #include "fetchhelper.h" #include "handlerhelper.h" #include "searchhelper.h" -#include "imapstreamparser.h" -#include "response.h" #include "search/searchrequest.h" #include "search/searchmanager.h" = -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/searchhelper.cpp b/src/server/handler/searc= hhelper.cpp index 3288421..01ae84d 100644 --- a/src/server/handler/searchhelper.cpp +++ b/src/server/handler/searchhelper.cpp @@ -19,8 +19,9 @@ *************************************************************************= **/ = #include "searchhelper.h" -#include "storage/countquerybuilder.h" + #include "entities.h" +#include "storage/countquerybuilder.h" = #include = diff --git a/src/server/handler/searchhelper.h b/src/server/handler/searchh= elper.h index 289ac8a..55740c5 100644 --- a/src/server/handler/searchhelper.h +++ b/src/server/handler/searchhelper.h @@ -20,10 +20,8 @@ #ifndef AKONADISEARCHHELPER_H #define AKONADISEARCHHELPER_H = -#include -#include -#include #include +#include = namespace Akonadi { namespace Server { diff --git a/src/server/handler/searchpersistent.cpp b/src/server/handler/s= earchpersistent.cpp index 53cfa53..e4b06b2 100644 --- a/src/server/handler/searchpersistent.cpp +++ b/src/server/handler/searchpersistent.cpp @@ -19,23 +19,15 @@ = #include "searchpersistent.h" = -#include "akonadi.h" #include "connection.h" -#include "response.h" +#include "handlerhelper.h" #include "storage/datastore.h" #include "storage/entity.h" #include "storage/transaction.h" -#include "handlerhelper.h" #include "search/searchmanager.h" -#include "imapstreamparser.h" - -#include -#include = #include = -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/searchresult.cpp b/src/server/handler/searc= hresult.cpp index 48c4fe2..309a215 100644 --- a/src/server/handler/searchresult.cpp +++ b/src/server/handler/searchresult.cpp @@ -20,14 +20,14 @@ */ = #include "searchresult.h" + #include "connection.h" -#include "imapstreamparser.h" #include "storage/selectquerybuilder.h" #include "storage/itemqueryhelper.h" #include "search/searchtaskmanager.h" = -#include -#include +#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/select.cpp b/src/server/handler/select.cpp index 00dc58a..b88526e 100644 --- a/src/server/handler/select.cpp +++ b/src/server/handler/select.cpp @@ -18,21 +18,11 @@ *************************************************************************= **/ #include "select.h" = -#include - -#include "akonadi.h" #include "connection.h" -#include "storage/datastore.h" -#include "storage/entity.h" #include "handlerhelper.h" -#include "imapstreamparser.h" -#include "storage/selectquerybuilder.h" -#include "storage/collectionstatistics.h" #include "commandcontext.h" = -#include "response.h" - -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/status.cpp b/src/server/handler/status.cpp index cce2fdc..80142da 100644 --- a/src/server/handler/status.cpp +++ b/src/server/handler/status.cpp @@ -16,22 +16,16 @@ * Free Software Foundation, Inc., = * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. = * *************************************************************************= **/ -#include "status.h" = -#include +#include "status.h" = -#include "akonadi.h" #include "connection.h" +#include "handlerhelper.h" #include "storage/datastore.h" -#include "storage/entity.h" #include "storage/countquerybuilder.h" #include "storage/collectionstatistics.h" = -#include "response.h" -#include "handlerhelper.h" -#include "imapstreamparser.h" - -#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/store.cpp b/src/server/handler/store.cpp index c412606..275a23f 100644 --- a/src/server/handler/store.cpp +++ b/src/server/handler/store.cpp @@ -19,10 +19,8 @@ = #include "store.h" = -#include "akonadi.h" #include "connection.h" #include "handlerhelper.h" -#include "response.h" #include "storage/datastore.h" #include "storage/transaction.h" #include "storage/itemqueryhelper.h" @@ -32,17 +30,12 @@ #include "storage/itemretriever.h" #include "storage/parttypehelper.h" #include "storage/partstreamer.h" -#include "imapstreamparser.h" = -#include -#include -#include - -#include #include -#include "akonadiserver_debug.h" #include = +#include "akonadiserver_debug.h" + #include #include = diff --git a/src/server/handler/store.h b/src/server/handler/store.h index 82783cb..1704392 100644 --- a/src/server/handler/store.h +++ b/src/server/handler/store.h @@ -23,9 +23,6 @@ = #include "handler.h" #include "entities.h" -#include "storage/entity.h" - -#include = namespace Akonadi { namespace Server { diff --git a/src/server/handler/tagappend.cpp b/src/server/handler/tagappen= d.cpp index 4738d67..f8c046c 100644 --- a/src/server/handler/tagappend.cpp +++ b/src/server/handler/tagappend.cpp @@ -18,16 +18,15 @@ */ = #include "tagappend.h" + #include "tagfetchhelper.h" #include "connection.h" -#include "imapstreamparser.h" -#include "response.h" #include "storage/datastore.h" #include "storage/querybuilder.h" #include "storage/countquerybuilder.h" -#include "entities.h" = -#include +#include +#include = using namespace Akonadi; using namespace Akonadi::Server; @@ -78,7 +77,7 @@ bool TagAppend::parseStream() return failureResponse("Failed to store tag"); } = - const QMap attrs =3D cmd.attributes(); + const Protocol::Attributes attrs =3D cmd.attributes(); for (auto iter =3D attrs.cbegin(), end =3D attrs.cend(); iter !=3D= end; ++iter) { TagAttribute attribute; attribute.setTagId(tagId); diff --git a/src/server/handler/tagfetch.cpp b/src/server/handler/tagfetch.= cpp index a8ebe1c..906b1c9 100644 --- a/src/server/handler/tagfetch.cpp +++ b/src/server/handler/tagfetch.cpp @@ -18,13 +18,9 @@ *************************************************************************= **/ = #include "tagfetch.h" -#include "imapstreamparser.h" #include "connection.h" #include "tagfetchhelper.h" = -#include -#include - using namespace Akonadi; using namespace Akonadi::Server; = diff --git a/src/server/handler/tagfetchhelper.cpp b/src/server/handler/tag= fetchhelper.cpp index e18414d..b7fd03b 100644 --- a/src/server/handler/tagfetchhelper.cpp +++ b/src/server/handler/tagfetchhelper.cpp @@ -19,15 +19,10 @@ = #include "tagfetchhelper.h" #include "handler.h" -#include "response.h" -#include "storage/querybuilder.h" -#include "storage/tagqueryhelper.h" -#include "entities.h" #include "connection.h" #include "utils.h" - -#include -#include +#include "storage/querybuilder.h" +#include "storage/tagqueryhelper.h" = using namespace Akonadi; using namespace Akonadi::Server; @@ -126,8 +121,6 @@ bool TagFetchHelper::fetchTags() = QDataStream stream(mConnection->socket()); = - Response response; - response.setUntagged(); while (tagQuery.isValid()) { const qint64 tagId =3D tagQuery.value(0).toLongLong(); Protocol::FetchTagsResponse response(tagId); diff --git a/src/server/handler/tagremove.cpp b/src/server/handler/tagremov= e.cpp index 6b8f13e..e81ffb9 100644 --- a/src/server/handler/tagremove.cpp +++ b/src/server/handler/tagremove.cpp @@ -18,12 +18,13 @@ */ = #include "tagremove.h" -#include "storage/querybuilder.h" + #include "storage/selectquerybuilder.h" #include "storage/queryhelper.h" #include "storage/datastore.h" = -#include +#include +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/tagstore.cpp b/src/server/handler/tagstore.= cpp index 541e479..5fde248 100644 --- a/src/server/handler/tagstore.cpp +++ b/src/server/handler/tagstore.cpp @@ -18,14 +18,13 @@ */ = #include "tagstore.h" + #include "tagfetchhelper.h" -#include "imapstreamparser.h" -#include "response.h" +#include "connection.h" #include "storage/datastore.h" #include "storage/querybuilder.h" = -#include -#include "connection.h" +#include = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handler/transaction.cpp b/src/server/handler/transa= ction.cpp index 1af012f..dfd714c 100644 --- a/src/server/handler/transaction.cpp +++ b/src/server/handler/transaction.cpp @@ -18,12 +18,8 @@ */ = #include "transaction.h" -#include "storage/datastore.h" #include "connection.h" -#include "response.h" -#include "imapstreamparser.h" - -#include +#include "storage/datastore.h" = using namespace Akonadi; using namespace Akonadi::Server; diff --git a/src/server/handlerhelper.cpp b/src/server/handlerhelper.cpp index d9da7ae..75262e7 100644 --- a/src/server/handlerhelper.cpp +++ b/src/server/handlerhelper.cpp @@ -18,7 +18,6 @@ *************************************************************************= **/ = #include "handlerhelper.h" -#include "imapstreamparser.h" #include "storage/countquerybuilder.h" #include "storage/datastore.h" #include "storage/selectquerybuilder.h" @@ -29,11 +28,10 @@ #include "handler.h" #include "connection.h" = -#include +#include +#include #include = -#include - using namespace Akonadi; using namespace Akonadi::Server; = @@ -82,53 +80,6 @@ QString HandlerHelper::pathForCollection(const Collectio= n &col) return parts.join(QLatin1String("/")); } = -int HandlerHelper::parseCachePolicy(const QByteArray &data, Collection &co= l, int start, bool *changed) -{ - bool inheritChanged =3D false; - bool somethingElseChanged =3D false; - - QList params; - int end =3D ImapParser::parseParenthesizedList(data, params, start); - for (int i =3D 0; i < params.count() - 1; i +=3D 2) { - const QByteArray key =3D params[i]; - const QByteArray value =3D params[i + 1]; - - if (key =3D=3D AKONADI_PARAM_INHERIT) { - const bool inherit =3D value =3D=3D "true"; - inheritChanged =3D col.cachePolicyInherit() !=3D inherit; - col.setCachePolicyInherit(inherit); - } else if (key =3D=3D AKONADI_PARAM_INTERVAL) { - const int interval =3D value.toInt(); - somethingElseChanged =3D somethingElseChanged || interval !=3D= col.cachePolicyCheckInterval(); - col.setCachePolicyCheckInterval(interval); - } else if (key =3D=3D AKONADI_PARAM_CACHETIMEOUT) { - const int timeout =3D value.toInt(); - somethingElseChanged =3D somethingElseChanged || timeout !=3D = col.cachePolicyCacheTimeout(); - col.setCachePolicyCacheTimeout(timeout); - } else if (key =3D=3D AKONADI_PARAM_SYNCONDEMAND) { - const bool syncOnDemand =3D value =3D=3D "true"; - somethingElseChanged =3D somethingElseChanged || syncOnDemand = !=3D col.cachePolicySyncOnDemand(); - col.setCachePolicySyncOnDemand(syncOnDemand); - } else if (key =3D=3D AKONADI_PARAM_LOCALPARTS) { - QList tmp; - QStringList partsList; - ImapParser::parseParenthesizedList(value, tmp); - Q_FOREACH (const QByteArray &ba, tmp) { - partsList << QString::fromLatin1(ba); - } - const QString parts =3D partsList.join(QLatin1String(" ")); - somethingElseChanged =3D somethingElseChanged || col.cachePoli= cyLocalParts() !=3D parts; - col.setCachePolicyLocalParts(parts); - } - } - - if (changed && (inheritChanged || (!col.cachePolicyInherit() && someth= ingElseChanged))) { - *changed =3D true; - } - - return end; -} - Protocol::CachePolicy HandlerHelper::cachePolicyResponse(const Collection&= col) { Protocol::CachePolicy cachePolicy; diff --git a/src/server/handlerhelper.h b/src/server/handlerhelper.h index 50a3f28..7e1f37e 100644 --- a/src/server/handlerhelper.h +++ b/src/server/handlerhelper.h @@ -21,7 +21,6 @@ #define AKONADIHANDLERHELPER_H = #include "entities.h" -#include "imapset_p.h" = #include #include @@ -31,6 +30,7 @@ namespace Akonadi { = class Scope; +class ImapSet; = namespace Protocol { class Ancestor; @@ -43,7 +43,6 @@ class FetchRelationsResponse; namespace Server { = class CommandContext; -class ImapStreamParser; class Connection; = /** @@ -63,14 +62,6 @@ public: static QString pathForCollection(const Collection &col); = /** - Parse cache policy and update the given Collection object accoording= ly. - @param changed Indicates whether or not the cache policy already ava= ilable in @p col - has actually changed - @todo Error handling. - */ - static int parseCachePolicy(const QByteArray &data, Collection &col, i= nt start =3D 0, bool *changed =3D 0); - - /** Returns the protocol representation of the cache policy of the given Collection object. */ @@ -111,11 +102,6 @@ public: static Protocol::FetchRelationsResponse fetchRelationsResponse(const R= elation &relation); = /** - Parses the listing/ancestor depth parameter. - */ - static int parseDepth(const QByteArray &depth); - - /** Converts a bytearray list of flag names into flag records. @throws HandlerException on errors during datbase operations */ diff --git a/src/server/imapstreamparser.cpp b/src/server/imapstreamparser.= cpp deleted file mode 100644 index 145586b..0000000 --- a/src/server/imapstreamparser.cpp +++ /dev/null @@ -1,849 +0,0 @@ -/* - Copyright (c) 2006 - 2007 Volker Krause - Copyright (c) 2009 Andras Mantia - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published= by - the Free Software Foundation; either version 2 of the License, or (at = your - option) any later version. - - This library is distributed in the hope that it will be useful, but WI= THOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public Lice= nse - along with this library; see the file COPYING.LIB. If not, write to t= he - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Bosto= n, MA - 02110-1301, USA. -*/ - -#include "imapstreamparser.h" -#include "response.h" -#include "tracer.h" - -#include -#include -#include -#include -#include - -using namespace Akonadi; -using namespace Akonadi::Server; - -ImapStreamParser::ImapStreamParser(QIODevice *socket) - : m_socket(socket) - , m_position(0) - , m_literalSize(0) - , m_peeking(false) - , m_timeout(30 * 1000) -{ -} - -ImapStreamParser::~ImapStreamParser() -{ -} - -void ImapStreamParser::setWaitTimeout(int msecs) -{ - m_timeout =3D msecs; -} - -QString ImapStreamParser::readUtf8String() -{ - QByteArray tmp; - tmp =3D readString(); - QString result =3D QString::fromUtf8(tmp); - return result; -} - -QByteArray ImapStreamParser::readString() -{ - QByteArray result; - if (!waitForMoreData(m_data.length() =3D=3D 0)) { - throw ImapParserException("Unable to read more data"); - } - stripLeadingSpaces(); - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - - // literal string - // TODO: error handling - if (hasLiteral()) { - while (!atLiteralEnd()) { - result +=3D readLiteralPart(); - } - return result; - } - - // quoted string - return parseQuotedString(); -} - -QByteArray ImapStreamParser::peekString() -{ - m_peeking =3D true; - int pos =3D m_position; - const QByteArray string =3D readString(); - m_position =3D pos; - m_peeking =3D false; - return string; -} - -bool ImapStreamParser::hasString() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int savedPos =3D m_position ; - stripLeadingSpaces(); - int pos =3D m_position; - m_position =3D savedPos; - if (m_data[pos] =3D=3D '{') { - return true; //literal string - } - if (m_data[pos] =3D=3D '"') { - return true; //quoted string - } - if (m_data[pos] !=3D ' ' && - m_data[pos] !=3D '(' && - m_data[pos] !=3D ')' && - m_data[pos] !=3D '[' && - m_data[pos] !=3D ']' && - m_data[pos] !=3D '\n' && - m_data[pos] !=3D '\r') { - return true; //unquoted string - } - - return false; //something else, not a string -} - -bool ImapStreamParser::hasLiteral(bool requestData) -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int savedPos =3D m_position; - stripLeadingSpaces(); - if (m_data[m_position] =3D=3D '{') { - int end =3D -1; - do { - end =3D m_data.indexOf('}', m_position); - if (!waitForMoreData(end =3D=3D -1)) { - throw ImapParserException("Unable to read more data"); - } - } while (end =3D=3D -1); - Q_ASSERT(end > m_position); - m_literalSize =3D m_data.mid(m_position + 1, end - m_position - 1)= .toInt(); - // strip CRLF - m_position =3D end + 1; - - //IMAP inconsistency. IMAP always expects CRLF, but akonadi uses o= nly LF. - if (m_position < m_data.length() && m_data[m_position] =3D=3D '\n'= ) { - ++m_position; - } - - if (m_literalSize >=3D 0 && requestData) { - sendContinuationResponse(m_literalSize); - } - return true; - } else { - m_position =3D savedPos; - return false; - } -} - -bool ImapStreamParser::atLiteralEnd() const -{ - return (m_literalSize =3D=3D 0); -} - -qint64 ImapStreamParser::remainingLiteralSize() -{ - return m_literalSize; -} - -QByteArray ImapStreamParser::readLiteralPart() -{ - static const qint64 maxLiteralPartSize =3D 4096; - int size =3D qMin(maxLiteralPartSize, m_literalSize); - - if (!waitForMoreData(m_data.length() < m_position + size)) { - throw ImapParserException("Unable to read more data"); - } - - if (m_data.length() < m_position + size) { // Still not enough data - // Take what's already there - size =3D m_data.length() - m_position; - } - - QByteArray result =3D m_data.mid(m_position, size); - m_position +=3D size; - m_literalSize -=3D size; - Q_ASSERT(m_literalSize >=3D 0); - if (!m_peeking) { - m_data =3D m_data.right(m_data.size() - m_position); - m_position =3D 0; - } - return result; -} - -bool ImapStreamParser::hasSequenceSet() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int savedPos =3D m_position; - stripLeadingSpaces(); - int pos =3D m_position; - m_position =3D savedPos; - - if (m_data[pos] =3D=3D '*' || m_data[pos] =3D=3D ':' || isdigit(m_dat= a[pos])) { - return true; - } - - return false; -} - -ImapSet ImapStreamParser::readSequenceSet() -{ - ImapSet result; - if (!waitForMoreData(m_data.length() =3D=3D 0)) { - throw ImapParserException("Unable to read more data"); - } - stripLeadingSpaces(); - qint64 value =3D -1, lower =3D -1, upper =3D -1; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D m_position)) { - upper =3D value; - if (lower < 0) { - lower =3D value; - } - if (lower >=3D 0 && upper >=3D 0) { - result.add(ImapInterval(lower, upper)); - } - return result; - } - - if (m_data[m_position] =3D=3D '*') { - value =3D 0; - } else if (m_data[m_position] =3D=3D ':') { - lower =3D value; - } else if (isdigit(m_data[m_position])) { - bool ok =3D false; - value =3D readNumber(&ok); - Q_ASSERT(ok); // TODO handle error - --m_position; - } else { - upper =3D value; - if (lower < 0) { - lower =3D value; - } - if ( lower >=3D 0 && upper >=3D 0 ) { - result.add(ImapInterval(lower, upper)); - } - lower =3D -1; - upper =3D -1; - value =3D -1; - if (m_data[m_position] !=3D ',') { - return result; - } - } - ++m_position; - } -} - -bool ImapStreamParser::hasList() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int savedPos =3D m_position; - stripLeadingSpaces(); - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int pos =3D m_position; - m_position =3D savedPos; - if (m_data[pos] =3D=3D '(') { - return true; - } - - return false; -} - -void ImapStreamParser::beginList() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - stripLeadingSpaces(); - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - if (m_data[m_position] !=3D '(') { - throw ImapParserException("Stream not at a beginning of a list"); - } - ++m_position; - return; -} - -bool ImapStreamParser::atListEnd() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int savedPos =3D m_position; - stripLeadingSpaces(); - int pos =3D m_position; - m_position =3D savedPos; - if (m_data[pos] =3D=3D ')') { - m_position =3D pos + 1; - return true; - } - - return false; -} - -QList ImapStreamParser::readParenthesizedList() -{ - QList result; - if (!waitForMoreData(m_data.length() <=3D m_position)) { - throw ImapParserException("Unable to read more data"); - } - - stripLeadingSpaces(); - if (m_data[m_position] !=3D '(') { - return result; //no list found - } - - bool concatToLast =3D false; - int count =3D 0; - int sublistbegin =3D m_position; - int i =3D m_position + 1; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D i)) { - m_position =3D i; - throw ImapParserException("Unable to read more data"); - } - if (m_data[i] =3D=3D '(') { - ++count; - if (count =3D=3D 1) { - sublistbegin =3D i; - } - ++i; - continue; - } - if (m_data[i] =3D=3D ')') { - if (count <=3D 0) { - m_position =3D i + 1; - return result; - } - if (count =3D=3D 1) { - result.append(m_data.mid(sublistbegin, i - sublistbegin + = 1)); - } - --count; - ++i; - continue; - } - if (m_data[i] =3D=3D ' ') { - ++i; - continue; - } - if (m_data.at(i) =3D=3D '"') { - if (count > 0) { - m_position =3D i; - parseQuotedString(); - i =3D m_position; - continue; - } - } - if (m_data[i] =3D=3D '[') { - concatToLast =3D true; - result.last() +=3D '['; - ++i; - continue; - } - if (m_data[i] =3D=3D ']') { - concatToLast =3D false; - result.last() +=3D ']'; - ++i; - continue; - } - if (count =3D=3D 0) { - m_position =3D i; - QByteArray ba; - if (hasLiteral()) { - while (!atLiteralEnd()) { - ba +=3D readLiteralPart(); - } - } else { - ba =3D readString(); - } - - // We might sometime get some unwanted CRLF, but we're still n= ot at the end - // of the list, would make further string reads fail so eat th= e CRLFs. - while ((m_position < m_data.size()) && - (m_data[m_position] =3D=3D '\r' || m_data[m_position] = =3D=3D '\n')) { - m_position++; - } - - i =3D m_position - 1; - if (concatToLast) { - result.last() +=3D ba; - } else { - result.append(ba); - } - } - ++i; - } - - throw ImapParserException("Something went very very wrong!"); -} - -QByteRef ImapStreamParser::readChar() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - m_position++; - return m_data[m_position - 1]; -} - -QDateTime ImapStreamParser::readDateTime() -{ - // Syntax: - // date-time =3D DQUOTE date-day-fixed "-" date-month "-" date-ye= ar - // SP time SP zone DQUOTE - // date-day-fixed =3D (SP DIGIT) / 2DIGIT - // ; Fixed-format version of date-day - // date-month =3D "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / - // "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" - // date-year =3D 4DIGIT - // time =3D 2DIGIT ":" 2DIGIT ":" 2DIGIT - // ; Hours minutes seconds - // zone =3D ("+" / "-") 4DIGIT - // ; Signed four-digit value of hhmm representing - // ; hours and minutes east of Greenwich (that is, - // ; the amount that the given time differs from - // ; Universal Time). Subtracting the timezone - // ; from the given time will give the UT form. - // ; The Universal Time zone is "+0000". - // Example : "28-May-2006 01:03:35 +0200" - // Position: 0123456789012345678901234567 - // 1 2 - - int savedPos =3D m_position; - if (!waitForMoreData(m_data.length() =3D=3D 0)) { - throw ImapParserException("Unable to read more data"); - } - stripLeadingSpaces(); - - bool quoted =3D false; - if (m_data[m_position] =3D=3D '"') { - quoted =3D true; - ++m_position; - - if (m_data.length() <=3D m_position + 26) { - m_position =3D savedPos; - return QDateTime(); - } - } else { - if (m_data.length() < m_position + 26) { - m_position =3D savedPos; - return QDateTime(); - } - } - - bool ok =3D true; - const int day =3D (m_data[m_position] =3D=3D ' ' ? m_data[m_position += 1] - '0' // single digit day - : m_data.mid(m_position, 2).toInt(&ok)); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - m_position +=3D 3; - const QByteArray shortMonthNames("janfebmaraprmayjunjulaugsepoctnovdec= "); - int month =3D shortMonthNames.indexOf(m_data.mid(m_position, 3).toLowe= r()); - if (month =3D=3D -1) { - m_position =3D savedPos; - return QDateTime(); - } - month =3D month / 3 + 1; - m_position +=3D 4; - const int year =3D m_data.mid(m_position, 4).toInt(&ok); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - m_position +=3D 5; - const int hours =3D m_data.mid(m_position, 2).toInt(&ok); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - m_position +=3D 3; - const int minutes =3D m_data.mid(m_position, 2).toInt(&ok); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - m_position +=3D 3; - const int seconds =3D m_data.mid(m_position, 2).toInt(&ok); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - m_position +=3D 4; - const int tzhh =3D m_data.mid(m_position, 2).toInt(&ok); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - m_position +=3D 2; - const int tzmm =3D m_data.mid(m_position, 2).toInt(&ok); - if (!ok) { - m_position =3D savedPos; - return QDateTime(); - } - int tzsecs =3D tzhh * 60 * 60 + tzmm * 60; - if (m_data[m_position - 3] =3D=3D '-') { - tzsecs =3D -tzsecs; - } - const QDate date(year, month, day); - const QTime time(hours, minutes, seconds); - QDateTime dateTime; - dateTime =3D QDateTime(date, time, Qt::UTC); - if (!dateTime.isValid()) { - m_position =3D savedPos; - return QDateTime(); - } - dateTime =3D dateTime.addSecs(-tzsecs); - - m_position +=3D 2; - if (m_data.length() <=3D m_position || !quoted) { - return dateTime; - } - if (m_data[m_position] =3D=3D '"') { - ++m_position; - } - return dateTime; -} - -bool ImapStreamParser::hasDateTime() -{ - int savedPos =3D m_position; - QDateTime dateTime =3D readDateTime(); - m_position =3D savedPos; - return !dateTime.isNull(); -} - -QByteArray ImapStreamParser::parseQuotedString() -{ - QByteArray result; - if (!waitForMoreData(m_data.length() =3D=3D 0)) { - throw ImapParserException("Unable to read more data"); - } - stripLeadingSpaces(); - int end =3D m_position; - result.clear(); - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - - bool foundSlash =3D false; - // quoted string - if (m_data[m_position] =3D=3D '"') { - ++m_position; - int i =3D m_position; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D i)) { - m_position =3D i; - throw ImapParserException("Unable to read more data"); - } - - if (foundSlash) { - foundSlash =3D false; - if (m_data[i] =3D=3D 'r') { - result +=3D '\r'; - } else if (m_data[i] =3D=3D 'n') { - result +=3D '\n'; - } else if (m_data[i] =3D=3D '\\') { - result +=3D '\\'; - } else if (m_data[i] =3D=3D '\"') { - result +=3D '\"'; - } else { - throw ImapParserException("Unexpected '\\' in quoted s= tring"); - } - ++i; - continue; - } - - if (m_data[i] =3D=3D '\\') { - foundSlash =3D true; - ++i; - continue; - } - - if (m_data[i] =3D=3D '"') { - end =3D i + 1; // skip the '"' - break; - } - - result +=3D m_data[i]; - - ++i; - } - } else { - // unquoted string - bool reachedInputEnd =3D true; - int i =3D m_position; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D i)) { - m_position =3D i; - throw ImapParserException("Unable to read more data"); - } - // unlike in the copy in KIMAP we do not want to consider [] b= rackets as separators, breaks payload version parsing - // if that ever gets fixed we can re-add them here, see svn re= vision 937879 - if (m_data[i] =3D=3D ' ' || m_data[i] =3D=3D '(' || m_data[i] = =3D=3D ')' || m_data[i] =3D=3D '\n' || m_data[i] =3D=3D '\r' || m_data[i] = =3D=3D '"') { - end =3D i; - reachedInputEnd =3D false; - break; - } - if (m_data[i] =3D=3D '\\') { - foundSlash =3D true; - } - i++; - } - if (reachedInputEnd) { //FIXME: how can it get here? - end =3D m_data.length(); - } - - result =3D m_data.mid(m_position, end - m_position); - - // transform unquoted NIL - if (result =3D=3D "NIL") { - result.clear(); - } - - // strip quotes - if (foundSlash) { - while (result.contains("\\\"")) { - result.replace("\\\"", "\""); - } - while (result.contains("\\\\")) { - result.replace("\\\\", "\\"); - } - } - } - - m_position =3D end; - return result; -} - -qint64 ImapStreamParser::readNumber(bool *ok) -{ - qint64 result; - if (ok) { - *ok =3D false; - } - if (!waitForMoreData(m_data.length() =3D=3D 0)) { - throw ImapParserException("Unable to read more data"); - } - stripLeadingSpaces(); - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - if (m_position >=3D m_data.length()) { - throw ImapParserException("Unable to read more data"); - } - int i =3D m_position; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D i)) { - m_position =3D i; - throw ImapParserException("Unable to read more data"); - } - if (!isdigit(m_data.at(i))) { - break; - } - ++i; - } - const QByteArray tmp =3D m_data.mid(m_position, i - m_position); - bool success =3D false; - result =3D tmp.toLongLong(&success); - if (ok) { - *ok =3D success; - } else if (!success) { - throw ImapParserException("Unable to parse number"); - } - m_position =3D i; - return result; -} - -void ImapStreamParser::stripLeadingSpaces() -{ - for (int i =3D m_position; i < m_data.length(); ++i) { - if (m_data[i] !=3D ' ') { - m_position =3D i; - return; - } - } - m_position =3D m_data.length(); -} - -bool ImapStreamParser::waitForMoreData(bool wait) -{ - if (wait) { - if (m_socket->bytesAvailable() > 0 || - m_socket->waitForReadyRead(m_timeout)) { - m_data.append(m_socket->readAll()); - } else { - return false; - } - } - return true; -} - -void ImapStreamParser::setData(const QByteArray &data) -{ - m_data =3D data; -} - -QByteArray ImapStreamParser::readRemainingData() -{ - return m_data.mid(m_position); -} - -bool ImapStreamParser::atCommandEnd() -{ - if (!waitForMoreData(m_position >=3D m_data.length())) { - throw ImapParserException("Unable to read more data"); - } - int savedPos =3D m_position; - stripLeadingSpaces(); - if (m_data[m_position] =3D=3D '\n' || m_data[m_position] =3D=3D '\r') { - if (m_position < m_data.length() && m_data[m_position] =3D=3D '\r'= ) { - ++m_position; - } - if (m_position < m_data.length() && m_data[m_position] =3D=3D '\n'= ) { - ++m_position; - } - // We'd better empty m_data from time to time before it grows out = of control - if (!m_peeking) { - m_data =3D m_data.right(m_data.size() - m_position); - m_position =3D 0; - } - return true; //command end - } - m_position =3D savedPos; - return false; //something else -} - -QByteArray ImapStreamParser::readUntilCommandEnd() -{ - QByteArray result; - int i =3D m_position; - int paranthesisBalance =3D 0; - bool inQuotedString =3D false; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D i)) { - m_position =3D i; - throw ImapParserException("Unable to read more data"); - } - if (!inQuotedString && m_data[i] =3D=3D '{') { - m_position =3D i - 1; - hasLiteral(); //init literal size - result.append(m_data.mid(i - 1, m_position - i + 1)); - while (!atLiteralEnd()) { - result.append(readLiteralPart()); - } - // Read the last character part and possible crlf - i =3D m_position; - do { - result.append(m_data[i]); - ++i; - } while (m_data[i] =3D=3D ' ' || m_data[i] =3D=3D '\n' || m_da= ta[i] =3D=3D '\r'); - } - - if (!inQuotedString && m_data[i] =3D=3D '(') { - paranthesisBalance++; - } - if (!inQuotedString && m_data[i] =3D=3D ')') { - paranthesisBalance--; - } - result.append(m_data[i]); - - if (m_data[i] =3D=3D '"') { - if (m_data[i - 1] !=3D '\\') { - inQuotedString =3D !inQuotedString; - } - } - - if ((i =3D=3D m_data.length() && paranthesisBalance =3D=3D 0) || m= _data[i] =3D=3D '\n' || m_data[i] =3D=3D '\r') { - // Make sure we return \r\n and not just \r - if (m_data[i] =3D=3D '\r' && m_data[i + 1] =3D=3D '\n') { - ++i; - result.append('\n'); - } - break; //command end - } - ++i; - } - m_position =3D i + 1; - // We'd better empty m_data from time to time before it grows out of c= ontrol - if (!m_peeking) { - m_data =3D m_data.right(m_data.size() - m_position); - m_position =3D 0; - } - return result; -} - -void ImapStreamParser::skipCurrentCommand() -{ - int i =3D m_position; - Q_FOREVER { - if (!waitForMoreData(m_data.length() <=3D i)) { - m_position =3D i; - throw ImapParserException("Unable to read more data"); - } - if (m_data[i] =3D=3D '\n' || m_data[i] =3D=3D '\r') { - break; //command end - } - ++i; - } - m_position =3D i + 1; - // We'd better empty m_data from time to time before it grows out of c= ontrol - if (!m_peeking) { - m_data =3D m_data.right(m_data.size() - m_position); - m_position =3D 0; - } -} - -void ImapStreamParser::sendContinuationResponse(qint64 size) -{ - const QByteArray block =3D "+ Ready for literal data (expecting " - + QByteArray::number(size) + " bytes)\r\n"; - m_socket->write(block); - m_socket->waitForBytesWritten(m_timeout); - - Tracer::self()->connectionOutput(m_tracerId, block); -} - -void ImapStreamParser::insertData(const QByteArray &data) -{ - m_data =3D m_data.insert(m_position, data); -} - -void ImapStreamParser::appendData(const QByteArray &data) -{ - m_data =3D m_data + data; -} - -void ImapStreamParser::setTracerIdentifier(const QString &id) -{ - m_tracerId =3D id; -} diff --git a/src/server/imapstreamparser.h b/src/server/imapstreamparser.h deleted file mode 100644 index 72dd32a..0000000 --- a/src/server/imapstreamparser.h +++ /dev/null @@ -1,286 +0,0 @@ -/* - Copyright (c) 2006 - 2007 Volker Krause - Copyright (c) 2009 Andras Mantia - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published= by - the Free Software Foundation; either version 2 of the License, or (at = your - option) any later version. - - This library is distributed in the hope that it will be useful, but WI= THOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - License for more details. - - You should have received a copy of the GNU Library General Public Lice= nse - along with this library; see the file COPYING.LIB. If not, write to t= he - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Bosto= n, MA - 02110-1301, USA. -*/ - -#ifndef AKONADI_IMAPSTREAMPARSER_P_H -#define AKONADI_IMAPSTREAMPARSER_P_H - -#include - -#include -#include -#include -#include -#include - -#include "exception.h" - -AKONADI_EXCEPTION_MAKE_INSTANCE(ImapParserException); - -class QIODevice; - -class ImapStreamParserTest; - -namespace Akonadi { -namespace Server { - -/** - Parser for IMAP messages that operates on a local socket stream. -*/ -class ImapStreamParser -{ - friend class ::ImapStreamParserTest; - -public: - /** - * Construct the parser. - * @param socket the local socket to work with. - */ - ImapStreamParser(QIODevice *socket); - - /** - * Destructor. - */ - ~ImapStreamParser(); - - /** - * Sets how long the parser should wait for socket to provide more dat= a before - * aborting with error. - * - * Default value is 30 seconds. This method is used mainly to speed up - * unittests. - */ - void setWaitTimeout(int msecs); - - /** - * Get a string from the message. If the upcoming data is not a quoted= string, unquoted string or a literal, - * the behavior is undefined. Use @ref hasString to be sure a string c= omes. This call might block. - * @return the next string from the message as an utf8 string - */ - QString readUtf8String(); - - /** - * Same as above, but without decoding it to utf8. - * @return the next string from the message - */ - QByteArray readString(); - - /** - * Same as above, but without actually moving the stream position forw= ard. - * @return the next string from the stream, without modifying the stre= am. - */ - QByteArray peekString(); - - /** - * Get he next IMAP sequence set. If the upcoming data is not an IMAP = sequence set, - * the behavior is undefined. Use @ref hasSequenceSet to be sure a seq= uence set comes. This call might block. - * @return the next IMAP sequence set. - */ - ImapSet readSequenceSet(); - - /** - * Get he next parenthesized list. If the upcoming data is not a paren= thesized list, - * the behavior is undefined. Use @ref hasList to be sure a string com= es. This call might block. - * @return the next parenthesized list. - */ - QList readParenthesizedList(); - - /** - * Read a single character. This call might block. - * @return the read character - */ - QByteRef readChar(); - - /** - * Get the next data as a number. This call might block. - * @param ok true if the data found was a number - * @return the number - */ - qint64 readNumber(bool *ok =3D 0); - - /** - * Check if the next data is a string or not. This call might block. - * @return true if a string follows - */ - bool hasString(); - - /** - * Check if the next data is a literal data or not. If a literal is fo= und, the - * internal position pointer is set to the beginning of the literal da= ta. - * This call might block. - * @return true if a literal follows - */ - bool hasLiteral(bool requestData =3D true); - - /** - * Read the next literal sequence. This might or might not be the full= data. Example code to read a literal would be: - * @code - * ImapStreamParser parser; - * ... - * if (parser.hasLiteral()) - * { - * while (!parser.atLiteralEnd()) - * { - * QByteArray data =3D parser.readLiteralPart(); - * // do something with the data - * } - * } - * @endcode - * - * This call might block. - * - * @return part of a literal data - */ - QByteArray readLiteralPart(); - - /** - * Check if the literal data end was reached. See @ref hasLiteral and = @ref readLiteralPart . - * @return true if the literal was completely read. - */ - bool atLiteralEnd() const; - - /** - * Get the amount of data that needs to be read for the last literal. = If this is called right after hasLiteral, the actual size of the literal da= ta - * is returned. - * @return the remaining literal size - */ - qint64 remainingLiteralSize(); - - /** - * Check if the next data is an IMAP sequence set. This call might blo= ck. - * @return true if an IMAP sequence set comes. - */ - bool hasSequenceSet(); - - /** - * Check if the next data is a parenthesized list. This call might blo= ck. - * @return true if a parenthesized list comes. - */ - bool hasList(); - - /** - * Begin reading a parenthesized list. This call might block. - * This call will throw an exception if the parser is not at a beginni= ng of a list, - * that is hasList() returns false. - * @see hasList(), atListEnd - */ - void beginList(); - - /** - * Check if the next data is a parenthesized list end. This call might = block. - * @return true if a parenthesized list end. In this case the closing p= arenthesis - * is read from the stream. - */ - bool atListEnd(); - - /** - * Read a date/time. - * @return the date and time or a null QDateTime, if no valid date/tim= e was found - */ - QDateTime readDateTime(); - - /** - * Check if the next element in the data stream is a date or not. - * @return true, if a valid date follows - */ - bool hasDateTime(); - - /** - * Check if the command end was reached - * @return true if the end of command is reached - */ - bool atCommandEnd(); - - /** - * Return everything that remained from the command, including not= yet - * requested literal parts. - * @return the remaining command data - * @see skipCurrentCommand - */ - QByteArray readUntilCommandEnd(); - - /** - * This reads until the end of the already sent command and d= oes not - * request not yet sent literal parts. - * @see readUntilCommandEnd - */ - void skipCurrentCommand(); - - /** - * Return all the data that was read from the socket, but not processe= d yet. - * @return the remaining unprocessed data - */ - QByteArray readRemainingData(); - - void setData(const QByteArray &data); - - /** - * Inserts some data back into the parse buffer at the current positio= n. - * @param data data to be inserted - */ - void insertData(const QByteArray &data); - - /** - * Appends some data to the end of the parse buffer. - * @param data data to be appended - */ - void appendData(const QByteArray &data); - - /** - * Skips everything until the first character that isn't a space. - */ - void stripLeadingSpaces(); - - /** - * Set the identification used for Tracer calls. - */ - void setTracerIdentifier(const QString &id); - - /** - * Inform the client to send more literal data. - * @param size size of the requested literal in bytes - */ - void sendContinuationResponse(qint64 size); - -private: - QByteArray parseQuotedString(); - - /** - * If the condition is true, wait for more data to be available from t= he socket. - * If no data comes after a timeout (30000ms), it aborts and returns f= alse. - * @param wait the condition - * @return true if more data is available - */ - bool waitForMoreData(bool wait); - - QIODevice *m_socket; - QByteArray m_data; - QByteArray m_tag; - QString m_tracerId; - int m_position; - qint64 m_literalSize; - bool m_peeking; - int m_timeout; - -}; - -} // namespace Server -} // namespace Akonadi - -#endif diff --git a/src/server/storage/parthelper.cpp b/src/server/storage/parthel= per.cpp index 3de5b82..b023cc1 100644 --- a/src/server/storage/parthelper.cpp +++ b/src/server/storage/parthelper.cpp @@ -23,21 +23,19 @@ #include "selectquerybuilder.h" #include "dbconfig.h" #include "parttypehelper.h" -#include "imapstreamparser.h" = #include #include #include -#include #include = #include #include -#include "akonadiserver_debug.h" #include - #include = +#include "akonadiserver_debug.h" + using namespace Akonadi; using namespace Akonadi::Server; = @@ -198,30 +196,6 @@ void PartHelper::removeFile(const QString &fileName) QFile::remove(fileName); } = -bool PartHelper::streamToFile(ImapStreamParser *streamParser, QFile &file,= QIODevice::OpenMode openMode) -{ - Q_ASSERT(openMode & QIODevice::WriteOnly); - - if (!file.isOpen()) { - if (!file.open(openMode)) { - throw PartHelperException("Unable to update item part"); - } - } else { - Q_ASSERT(file.openMode() & QIODevice::WriteOnly); - } - - QByteArray value; - while (!streamParser->atLiteralEnd()) { - value =3D streamParser->readLiteralPart(); - if (file.write(value) !=3D value.size()) { - throw PartHelperException("Unable to write payload to file"); - } - } - file.close(); - - return true; -} - QByteArray PartHelper::translateData(const QByteArray &data, bool isExtern= al) { if (isExternal) { diff --git a/src/server/storage/parthelper.h b/src/server/storage/parthelpe= r.h index b266ebf..235f3c1 100644 --- a/src/server/storage/parthelper.h +++ b/src/server/storage/parthelper.h @@ -69,15 +69,6 @@ bool remove(const QString &column, const QVariant &value= ); */ void removeFile(const QString &fileName); = -/** - * Reads data from @p streamParser as they arrive from client and writes t= hem - * to @p partFile. It will close the file when all data are read. - * - * @param partFile File to write into. The file must be closed, or opened = in write mode - * @throws PartHelperException when an error occurs (write fails, data tru= ncated, etc) - */ -bool streamToFile(ImapStreamParser *streamParser, QFile &partFile, QIODevi= ce::OpenMode =3D QIODevice::WriteOnly); - /** Returns the payload data. */ QByteArray translateData(const QByteArray &data, bool isExternal); /** Convenience overload of the above. */ diff --git a/src/server/storage/partstreamer.cpp b/src/server/storage/parts= treamer.cpp index 4ef0ca7..0676595 100644 --- a/src/server/storage/partstreamer.cpp +++ b/src/server/storage/partstreamer.cpp @@ -24,10 +24,7 @@ #include "dbconfig.h" #include "connection.h" #include "capabilities_p.h" -#include "imapstreamparser.h" -#include "response.h" = -#include #include #include = diff --git a/src/server/storagejanitor.cpp b/src/server/storagejanitor.cpp index f44c0db..f05818a 100644 --- a/src/server/storagejanitor.cpp +++ b/src/server/storagejanitor.cpp @@ -34,6 +34,7 @@ #include #include = +#include #include #include =20