summaryrefslogtreecommitdiff
path: root/noncore/unsupported/mail2/libmail/imapresponse.cpp
Unidiff
Diffstat (limited to 'noncore/unsupported/mail2/libmail/imapresponse.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/mail2/libmail/imapresponse.cpp448
1 files changed, 448 insertions, 0 deletions
diff --git a/noncore/unsupported/mail2/libmail/imapresponse.cpp b/noncore/unsupported/mail2/libmail/imapresponse.cpp
new file mode 100644
index 0000000..06dca33
--- a/dev/null
+++ b/noncore/unsupported/mail2/libmail/imapresponse.cpp
@@ -0,0 +1,448 @@
1#include "imapresponse.h"
2
3static QString _previousData;
4static unsigned int _neededData;
5
6IMAPResponseParser::IMAPResponseParser(const QString &data)
7 {
8 QString _data = data, more;
9 _data.replace((QString)"\r\n", "\n");
10
11 QStringList lines = QStringList::split('\n', _data);
12 QStringList::Iterator it;
13 for (it = lines.begin(); it != lines.end(); it++) {
14 QString tag, lineData;
15
16 if (!_previousData.isNull()) {
17 qDebug(QString("IMAPResponseParser: got additional data. (%1/%2)").arg(_previousData.length()).arg(_neededData));
18 _previousData += *it + "\n";
19 if (_previousData.length() >= _neededData) {
20 _previousData += ")";
21 qDebug("IMAPResponseParser: got ALL additional data.");
22 qDebug("Data is: " + _previousData);
23 parseResponse(_previousData);
24 _previousData = QString(0);
25 _neededData = 0;
26 }
27 } else {
28 splitTagData(*it, tag, lineData);
29 if (tag == "*") {
30 int pos;
31 if ((pos = data.find(QRegExp("\\{\\d*\\}"))) != -1) {
32 qDebug("IMAPResponseParser: waiting for additional data...");
33 _previousData = lineData + "\n";
34
35 QString tmp = data.right(data.length() - pos - 1).stripWhiteSpace();
36 tmp.truncate(tmp.length() - 1);
37
38 _neededData = tmp.toUInt();
39 if (_previousData.length() >= _neededData) {
40 qDebug("IMAPResponseParser: got ALL additional data. (1st)");
41 parseResponse(_previousData);
42 _previousData = QString(0);
43 _neededData = 0;
44 } else {
45 break;
46 }
47 } else {
48 parseResponse(lineData);
49 }
50 } else if (tag == "+") {
51 emit needMoreData(_data);
52 } else {
53 _iresponse.setTag(tag);
54 parseResponse(_data, true);
55 }
56 }
57 }
58}
59
60IMAPResponse IMAPResponseParser::response()
61{
62 return _iresponse;
63}
64
65void IMAPResponseParser::parseResponse(const QString &data, bool tagged)
66{
67 QString response, line;
68 int pos;
69 bool isNum = false;
70 if ((pos = data.find(' ')) != -1) {
71 response = data.left(pos).upper();
72 response.toInt(&isNum);
73 line = data.right(data.length() - pos - 1);
74 } else {
75 qWarning("IMAPResponseParser: parseResponse: No response found.");
76 return;
77 }
78
79 if (response == "OK" && tagged) {
80 IMAPResponseStatusResponse status(OK, line);
81 status.setResponseCode(getResponseCode(status.comment()));
82 _iresponse.setStatusResponse(status);
83 } else if (response == "OK" && !tagged) {
84 IMAPResponseOK ok(line, getResponseCode(line));
85 _iresponse.addOK(ok);
86 } else if (response == "NO" && tagged) {
87 IMAPResponseStatusResponse status(NO, line);
88 status.setResponseCode(getResponseCode(status.comment()));
89 _iresponse.setStatusResponse(status);
90 } else if (response == "NO" && !tagged) {
91 IMAPResponseNO no(line, getResponseCode(line));
92 _iresponse.addNO(no);
93 } else if (response == "BAD" && tagged) {
94 IMAPResponseStatusResponse status(BAD, line);
95 status.setResponseCode(getResponseCode(status.comment()));
96 _iresponse.setStatusResponse(status);
97 } else if (response == "BAD" && !tagged) {
98 IMAPResponseBAD bad(line, getResponseCode(line));
99 _iresponse.addBAD(bad);
100 } else if (response == "PREAUTH" && tagged) {
101 IMAPResponseStatusResponse status(PREAUTH, line);
102 _iresponse.setStatusResponse(status);
103 } else if (response == "PREAUTH" && !tagged) {
104 qDebug("IMAPResponseParser: responseParser: got untagged PREAUTH response.");
105 // XXX
106 } else if (response == "BYE") {
107 IMAPResponseStatusResponse status(BYE, line);
108 if (!tagged) status.setExitedUnexpected(true);
109 _iresponse.setStatusResponse(status);
110 } else if (response == "CAPABILITY") {
111 IMAPResponseCAPABILITY capability(QStringList::split(' ', line));
112 _iresponse.addCAPABILITY(capability);
113 } else if (response == "LIST") {
114 QStringList list = splitData(line, true);
115
116 QStringList flags;
117 parseParenthesizedList(list[0], flags);
118
119 removeLimiters(list[1]);
120 removeLimiters(list[2]);
121 IMAPResponseLIST rlist(parseFlagList(flags), list[1], list[2]);
122 _iresponse.addLIST(rlist);
123 } else if (response == "LSUB") {
124 QStringList list = splitData(line, true);
125
126 QStringList flags;
127 parseParenthesizedList(list[0], flags);
128
129 removeLimiters(list[1]);
130 removeLimiters(list[2]);
131 IMAPResponseLSUB lsub(parseFlagList(flags), list[1], list[2]);
132 _iresponse.addLSUB(lsub);
133 } else if (response == "STATUS") {
134 QStringList list = splitData(line, true);
135
136 removeLimiters(list[0]);
137 IMAPResponseSTATUS status(list[0]);
138
139 QStringList flags;
140 parseParenthesizedList(list[1], flags);
141 QStringList::Iterator it;
142 for (it = flags.begin(); it != flags.end(); it++) {
143 if (*it == "MESSAGES") status.setMessages(*(++it));
144 else if (*it == "RECENT") status.setRecent(*(++it));
145 else if (*it == "UIDNEXT") status.setUidnext(*(++it));
146 else if (*it == "UIDVALIDITY") status.setUidvalidity(*(++it));
147 else if (*it == "UNSEEN") status.setUnseen(*(++it));
148 else qWarning("IMAPResponseParser: parseResponse: Unknown status data: " + *(it++) + "|");
149 }
150 _iresponse.addSTATUS(status);
151 } else if (response == "SEARCH") {
152 IMAPResponseSEARCH search(QStringList::split(' ', line));
153 _iresponse.addSEARCH(search);
154 } else if (response == "FLAGS") {
155 QStringList list;
156 parseParenthesizedList(line, list);
157
158 IMAPResponseFLAGS flags(parseFlagList(list));
159 _iresponse.addFLAGS(flags);
160 } else if (isNum) {
161 QStringList list = QStringList::split(' ', line);
162 if (list[0] == "EXISTS") {
163 IMAPResponseEXISTS exists(response);
164 _iresponse.addEXISTS(exists);
165 } else if (list[0] == "RECENT") {
166 IMAPResponseRECENT recent(response);
167 _iresponse.addRECENT(recent);
168 } else if (list[0] == "EXPUNGE") {
169 IMAPResponseEXPUNGE expunge(response);
170 _iresponse.addEXPUNGE(expunge);
171 } else if (list[0] == "FETCH") {
172 IMAPResponseFETCH fetch;
173 QStringList::Iterator it;
174
175 QStringList fetchList = splitData(line, true);
176 QStringList list;
177 parseParenthesizedList(fetchList[1], list);
178
179 for (it = list.begin(); it != list.end(); it++) {
180 if (*it == "BODY") {
181 qDebug("IMAPResponseParser: responseParser: got FETCH::BODY");
182 // XXX
183 } else if ((*it).find(QRegExp("BODY\\[\\d+\\]")) != -1) {
184 QString bodydata = *(++it);
185 qDebug("IMAPResponseParser: responseParser: got FETCH::BODY[x]");
186
187 QStringList blist;
188 parseParenthesizedList(bodydata, blist);
189
190 IMAPResponseBodyPart bodypart;
191 QString tmp;
192 for (unsigned int i = 2; i < blist.count(); i++) {
193 if (i != 2) tmp += " " + blist[i];
194 else tmp += blist[i];
195 }
196 bodypart.setData(tmp);
197
198 tmp = list[0];
199 tmp.replace(0, 5, "");
200 tmp.truncate(blist[0].length() - 1);
201 bodypart.setPart(tmp);
202
203 fetch.addBodyPart(bodypart);
204 } else if (*it == "BODYSTRUCTURE") {
205 qDebug("IMAPResponseParser: responseParser: got FETCH::BODYSTRUCTURE");
206/*
207 QString bsdata = *(++it);
208 QStringList bsList;
209 parseParenthesizedList(bsdata, bsList);
210
211 IMAPResponseBodystructure bodystructure;
212 QStringList attachml;
213
214 for (int i = 0; i < bsList.count() - 1; i++) {
215 parseParenthesizedList(bsList[0], attachml);
216
217 IMAPResponseBodypart bodypart;
218 bodypart.setMimeTypeMain(attachml[0] == "NIL" ? QString(0) : attachml[0]);
219 bodypart.setMimeTypeSub(attachml[1] == "NIL" ? QString(0) : attachml[1]);
220 bodypart.setAddData(attachml[2] == "NIL" ? QString(0) : attachml[2]);
221 // 3 (NIL)
222 // 4 (NIL)
223 bodypart.setEncoding(attachml[5] == "NIL" ? QString(0) : attachml[5]);
224 bodypart.setSize(attachml[6] == "NIL" ? QString(0) : attachml[6]);
225 bodypart.setLength(attachml[7] == "NIL" ? QString(0) : attachml[7]);
226 bodypart.setAttachInfo(attachml[8] == "NIL" ? QString(0) : attachml[8]);
227 // 9 (NIL)
228 // 10 (NIL)
229
230 bodystructure.addBodyPart(bodypart);
231 }
232*/
233 } else if (*it == "ENVELOPE") {
234 QString envdata = *(++it);
235 QStringList envList;
236 parseParenthesizedList(envdata, envList);
237
238 IMAPResponseEnvelope envelope;
239 envelope.setMailDate(envList[0] == "NIL" ? QString(0) : removeLimiters(envList[0]));
240 envelope.setSubject(envList[1] == "NIL" ? QString(0) : removeLimiters(envList[1]));
241
242 QStringList froml, senderl, replytol, tol, ccl, bccl;
243 QStringList froma, sendera, replytoa, toa, cca, bcca;
244 parseParenthesizedList(envList[2], froml);
245 parseParenthesizedList(envList[3], senderl);
246 parseParenthesizedList(envList[4], replytol);
247 parseParenthesizedList(envList[5], tol);
248 parseParenthesizedList(envList[6], ccl);
249 parseParenthesizedList(envList[7], bccl);
250
251 QStringList::Iterator it;
252 for (it = froml.begin(); it != froml.end(); it++) {
253 parseParenthesizedList(*it, froma);
254 if (froml[0] != "NIL")
255 envelope.addFrom(IMAPResponseAddress(
256 removeLimiters(froma[0]),
257 removeLimiters(froma[1]),
258 removeLimiters(froma[2]),
259 removeLimiters(froma[3])));
260 }
261
262 for (it = senderl.begin(); it != senderl.end(); it++) {
263 parseParenthesizedList(*it, sendera);
264 if (senderl[0] != "NIL")
265 envelope.addSender(IMAPResponseAddress(
266 removeLimiters(sendera[0]),
267 removeLimiters(sendera[1]),
268 removeLimiters(sendera[2]),
269 removeLimiters(sendera[3])));
270 }
271
272 for (it = replytol.begin(); it != replytol.end(); it++) {
273 parseParenthesizedList(*it, replytoa);
274 if (replytol[0] != "NIL")
275 envelope.addReplyTo(IMAPResponseAddress(
276 removeLimiters(replytoa[0]),
277 removeLimiters(replytoa[1]),
278 removeLimiters(replytoa[2]),
279 removeLimiters(replytoa[3])));
280 }
281
282 for (it = tol.begin(); it != tol.end(); it++) {
283 parseParenthesizedList(*it, toa);
284 if (tol[0] != "NIL")
285 envelope.addTo(IMAPResponseAddress(
286 removeLimiters(toa[0]),
287 removeLimiters(toa[1]),
288 removeLimiters(toa[2]),
289 removeLimiters(toa[3])));
290 }
291
292 for (it = ccl.begin(); it != ccl.end(); it++) {
293 parseParenthesizedList(*it, cca);
294 if (ccl[0] != "NIL")
295 envelope.addCc(IMAPResponseAddress(
296 removeLimiters(cca[0]),
297 removeLimiters(cca[1]),
298 removeLimiters(cca[2]),
299 removeLimiters(cca[3])));
300 }
301
302 for (it = bccl.begin(); it != bccl.end(); it++) {
303 parseParenthesizedList(*it, bcca);
304 if (bccl[0] != "NIL")
305 envelope.addBcc(IMAPResponseAddress(
306 removeLimiters(bcca[0]),
307 removeLimiters(bcca[1]),
308 removeLimiters(bcca[2]),
309 removeLimiters(bcca[3])));
310 }
311
312 envelope.setInReplyTo(envList[7] == "NIL" ? QString(0) : removeLimiters(envList[7]));
313 envelope.setMessageId(envList[8] == "NIL" ? QString(0) : removeLimiters(envList[8]));
314
315 fetch.setEnvelope(envelope);
316 } else if (*it == "FLAGS") {
317 QString flagdata = *(++it);
318 QStringList flags;
319 parseParenthesizedList(flagdata, flags);
320 fetch.setFlags(parseFlagList(flags));
321 } else if (*it == "INTERNALDATE") {
322 fetch.setInternalDate(removeLimiters(*(++it)));
323 } else if (*it == "RFC822" || *it == "BODY[]") {
324 qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822");
325 // XXX
326 } else if (*it == "RFC822.HEADER" || *it == "BODY.PEEK[HEADER]") {
327 qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822.HEADER");
328 // XXX
329 } else if (*it == "RFC822.SIZE") {
330 fetch.setRFC822Size(*(++it));
331 } else if (*it == "RFC822.TEXT" || *it == "BODY[TEXT]") {
332 qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822.TEXT");
333 // XXX
334 } else if (*it == "UID") {
335 fetch.setUid(*(++it));
336 }
337 }
338 _iresponse.addFETCH(fetch);
339 }
340 } else qWarning("IMAPResponseParser: parseResponse: Unknown response: " + response + "|");
341}
342
343QStringList IMAPResponseParser::splitData(const QString &data, bool withBrackets)
344{
345 int b = 0;
346 bool a = false, noappend = false, escaped = false;
347 QString temp;
348 QStringList list;
349
350 for (unsigned int i = 0; i <= data.length(); i++) {
351 if (withBrackets && data[i] == '(' && !a) b++;
352 else if (withBrackets && data[i] == ')' && !a) b--;
353
354 if (data[i] == '"' && !escaped) a = !a;
355 else escaped = false;
356
357 if (data[i] == '\\' && data[i + 1] == '"') escaped = true;
358
359 if ((data[i] == ' ' || i == data.length()) && b == 0 && !a) {
360 list.append(temp);
361 temp = QString(0);
362 if (data[i] == ' ') noappend = true;
363 }
364
365 if (!noappend) temp += data[i];
366 noappend = false;
367 }
368
369 return list;
370}
371
372void IMAPResponseParser::parseParenthesizedList(const QString &data, QStringList &parsed)
373{
374 QString data_(data);
375 removeLimiters(data_, '(', ')');
376 parsed = splitData(data_, true);
377}
378
379void IMAPResponseParser::splitTagData(const QString &line, QString &tag, QString &data)
380{
381 int pos;
382 if ((pos = line.find(' ')) != -1) {
383 tag = line.left(pos);
384 data = line.right(line.length() - pos - 1);
385 } else qWarning("IMAPResponseParser: splitTagData: tag not found. Line was " + line + "|");
386}
387
388QString IMAPResponseParser::removeLimiters(QString &string, const QChar &sl, const QChar &el)
389{
390 QString tmpString;
391 if (string[0] == sl && string[string.length() - 1] == el) {
392 string.truncate(string.length() - 1);
393 string.replace(0, 1, "");
394
395 for (unsigned int i = 1; i <= string.length(); i++) {
396 if (string[i - 1] == '\\' && sl == '"') ++i;
397 tmpString += string[i - 1];
398 }
399 }
400
401 return tmpString;
402}
403
404IMAPResponseEnums::IMAPResponseCode IMAPResponseParser::getResponseCode(const QString &line)
405{
406 if (line.find(QRegExp((QString) "^\\[.*\\]" + ' ' + ".*")) != -1) {
407 int pos = line.find("] ");
408 QString code = line.left(pos + 1).upper();
409
410 if (code.find(QRegExp("[ALERT]")) != -1) return ALERT;
411 else if (code.find(QRegExp("[NEWNAME .* .*]")) != -1) return NEWNAME; // XXX
412 else if (code.find(QRegExp("[PARSE]")) != -1) return PARSE;
413 else if (code.find(QRegExp("[PERMANENTFLAGS \\d*]")) != -1) return PERMANENTFLAGS; // XXX
414 else if (code.find(QRegExp("[READ-ONLY]")) != -1) return READONLY;
415 else if (code.find(QRegExp("[READ-WRITE]")) != -1) return READWRITE;
416 else if (code.find(QRegExp("[TRYCREATE]")) != -1) return TRYCREATE;
417 else if (code.find(QRegExp("[UIDVALIDITY \\d*]")) != -1) return UIDVALIDITY; // XXX
418 else if (code.find(QRegExp("[UNSEEN \\d*]")) != -1) return UNSEEN; // XXX
419 else {
420 qWarning("IMAPResponseParser: getResponseCode: Unknown code: " + code + "|");
421 return UnknownCode;
422 }
423 }
424 return NoCode;
425}
426
427QValueList<IMAPResponseEnums::IMAPResponseFlags> IMAPResponseParser::parseFlagList(const QStringList &flagList)
428{
429 QValueList<IMAPResponseFlags> flags;
430 QStringList::ConstIterator it;
431 for (it = flagList.begin(); it != flagList.end(); it++) {
432 QString flag = (*it).lower();
433 if (flag == "\\seen") flags.append(Seen);
434 else if (flag == "\\answered") flags.append(Answered);
435 else if (flag == "\\flagged") flags.append(Flagged);
436 else if (flag == "\\deleted") flags.append(Deleted);
437 else if (flag == "\\draft") flags.append(Draft);
438 else if (flag == "\\recent") flags.append(Recent);
439 else if (flag == "\\noinferiors") flags.append(Noinferiors);
440 else if (flag == "\\noselect") flags.append(Noselect);
441 else if (flag == "\\marked") flags.append(Marked);
442 else if (flag == "\\unmarked") flags.append(Unmarked);
443 else if (flag.isEmpty()) { }
444 else qWarning("IMAPResponseParser: parseFlagList: Unknown flag: " + *it + "|");
445 }
446 return flags;
447}
448