-rw-r--r-- | noncore/unsupported/mail2/libmail/configfile.cpp | 4 | ||||
-rw-r--r-- | noncore/unsupported/mail2/libmail/imapbase.cpp | 36 | ||||
-rw-r--r-- | noncore/unsupported/mail2/libmail/imapbase.h | 3 | ||||
-rw-r--r-- | noncore/unsupported/mail2/libmail/imaphandler.cpp | 7 | ||||
-rw-r--r-- | noncore/unsupported/mail2/libmail/imapresponse.cpp | 224 | ||||
-rw-r--r-- | noncore/unsupported/mail2/libmail/imapresponse.h | 5 | ||||
-rw-r--r-- | noncore/unsupported/mail2/viewmail.cpp | 4 |
7 files changed, 194 insertions, 89 deletions
diff --git a/noncore/unsupported/mail2/libmail/configfile.cpp b/noncore/unsupported/mail2/libmail/configfile.cpp index a5c2b49..082b330 100644 --- a/noncore/unsupported/mail2/libmail/configfile.cpp +++ b/noncore/unsupported/mail2/libmail/configfile.cpp @@ -41,72 +41,72 @@ ConfigFile::ConfigFile() : QObject() account.setReplyTo(config->readEntry("ReplyTo")); account.setSignature(config->readEntry("Signature").replace(QRegExp("<br>"), "\n")); _accounts.append(account); } } QValueList<Account> ConfigFile::getAccounts() { ConfigFile *configFile = new ConfigFile(); return configFile->_accounts; } void ConfigFile::updateAccount(Account account) { checkDirectory(); Config *config = new Config((QString) getenv("HOME") + "/Applications/mail/accounts/account-" + account.accountName(), Config::File); config->setGroup("Account"); config->writeEntry("RealName", account.realName()); config->writeEntry("Email", account.email()); config->writeEntry("Organization", account.org()); config->writeEntry("ImapServer", account.imapServer()); config->writeEntry("ImapPort", account.imapPort()); config->writeEntry("SmtpServer", account.smtpServer()); config->writeEntry("SmtpPort", account.smtpPort()); config->writeEntry("User", account.user()); config->writeEntryCrypt("Pass", rot13(account.pass())); config->writeEntry("SmtpSsl", account.smtpSsl()); config->writeEntry("SmtpSslPort", account.smtpSslPort()); config->writeEntry("ImapSsl", account.imapSsl()); config->writeEntry("ImapSslPort", account.imapSslPort()); config->writeEntry("DefaultCc", account.defaultCc()); config->writeEntry("DefaultBcc", account.defaultBcc()); config->writeEntry("DefaultReplyTo", account.defaultReplyTo()); config->writeEntry("Cc", account.cc()); config->writeEntry("Bcc", account.bcc()); config->writeEntry("ReplyTo", account.replyTo()); config->writeEntry("Signature", account.signature().replace(QRegExp("\\n"), "<br>")); config->write(); } void ConfigFile::deleteAccount(Account account) { QFile f((QString) getenv("HOME") + "/Applications/mail/accounts/account-" + account.accountName()); f.remove(); } void ConfigFile::checkDirectory() { if (!QDir((QString) getenv("HOME") + "/Applications/mail/accounts").exists()) { system("mkdir -p $HOME/Applications/mail/accounts"); qWarning("mail: $HOME/Applications/mail/accounts created"); } } QString ConfigFile::rot13(const QString &input) { QString i = input; int l = i.length(); while(l--) { if (i[l] >= QChar('A') && i[l] <= QChar('M') || i[l] >= QChar('a') && i[l] <= QChar('m')) - i[l] = (char)((int)QChar(l[i])+13); + i[l] = QChar(i[l].unicode()+13); else if (i[l] >= QChar('N') && i[l] <= QChar('Z') || i[l] >= QChar('n') && i[l] <= QChar('z')) - i[l] = (char)((int)QChar(l[i])-13); + i[l] = QChar(i[l].unicode()-13); } return i; } diff --git a/noncore/unsupported/mail2/libmail/imapbase.cpp b/noncore/unsupported/mail2/libmail/imapbase.cpp index 9a2ba47..4753f43 100644 --- a/noncore/unsupported/mail2/libmail/imapbase.cpp +++ b/noncore/unsupported/mail2/libmail/imapbase.cpp @@ -1,110 +1,132 @@ #include <qsocket.h> #include <qtimer.h> #include "imapbase.h" IMAPBase::IMAPBase(const Account &account) : QObject(), _account(account) { _connected = false; _writingAllowed = false; _socket = new QSocket(this); connect(_socket, SIGNAL(readyRead()), SLOT(slotDataAvailiable())); connect(_socket, SIGNAL(hostFound()), SLOT(slotHostFound())); connect(_socket, SIGNAL(connected()), SLOT(slotConnected())); connect(_socket, SIGNAL(connectionClosed()), SLOT(slotDisconnected())); connect(_socket, SIGNAL(error(int)), SLOT(slotError(int))); QTimer *commandTimer = new QTimer(this); commandTimer->start(200); connect(commandTimer, SIGNAL(timeout()), SLOT(writeCommands())); } void IMAPBase::sendCommand(const QString &command) { if (!_connected) makeConnect(); _commandQueue.append(command); } void IMAPBase::disconnect() { _connected = false; delete _socket; emit disconnected(); } void IMAPBase::makeConnect() { emit lookingUpHost(); if (_socket == NULL) _socket = new QSocket(this); Q_UINT16 port = _account.imapPort().toUInt(); _socket->connectToHost(_account.imapServer(), port); } void IMAPBase::writeCommands() { if (!_connected) return; if (_commandQueue.isEmpty()) return; if (!_writingAllowed) return; QStringList::Iterator it; for (it = _commandQueue.begin(); it != _commandQueue.end(); it++) { if (!(*it).isEmpty() && _writingAllowed) { #ifndef QT_NO_DEBUG - qDebug("IMAP > " + (*it).stripWhiteSpace()); + qDebug("IMAP > " + (*it).stripWhiteSpace().local8Bit ()); #endif _socket->writeBlock((*it).latin1(), (*it).length()); _writingAllowed = false; + if (( *it ). find ( QRegExp ( "^[a-z][0-9]+ " )) == 0 ) + _lasttag = (*it).left(2); + + connect(_socket, SIGNAL(readyRead()), SLOT(slotDataAvailiable())); _commandQueue.remove(it); break; } } } void IMAPBase::slotError(int err) { if (err == QSocket::ErrConnectionRefused) { emit error(IMAPErrConnectionRefused); } else if (err == QSocket::ErrHostNotFound) { emit error(IMAPErrHostNotFound); } else if (err == QSocket::ErrSocketRead) { emit error(IMAPErrSocketRead); } else { emit error(IMAPErrUnknownError); } } void IMAPBase::slotHostFound() { emit hostFound(); } void IMAPBase::slotConnected() { _connected = true; emit connected(); } void IMAPBase::slotDisconnected() { _connected = false; emit disconnected(); } +#include <unistd.h> + void IMAPBase::slotDataAvailiable() { + static bool firstline = true; + while (_socket->canReadLine()) { - _data += _socket->readLine(); - if (_socket->atEnd()) { -#ifndef QT_NO_DEBUG - qDebug("IMAP < " + _data.stripWhiteSpace()); -#endif + QString tmp = _socket-> readLine ( ); + + _data += tmp; + qDebug ( "New Line [%d]: '%s'\n", _connected ? 1 : 0, tmp.latin1( )); + + if ( firstline || tmp. left(2) == _lasttag ) { + firstline = false; + +// if ( _socket-> atEnd ( )) + qDebug ( "at end -> emitting\n" ); + + QObject::disconnect(_socket, SIGNAL(readyRead()), this, SLOT(slotDataAvailiable())); emit dataReceived(_data); + _data = QString::null; _writingAllowed = true; - _data = QString(0); } } } +void IMAPBase::tryRead ( QString &data ) +{ + qDebug ( "Trying to read...\n" ); + + while ( _socket-> canReadLine ( )) + data += _socket-> readLine ( ); +} diff --git a/noncore/unsupported/mail2/libmail/imapbase.h b/noncore/unsupported/mail2/libmail/imapbase.h index e4a0b97..7697ffe 100644 --- a/noncore/unsupported/mail2/libmail/imapbase.h +++ b/noncore/unsupported/mail2/libmail/imapbase.h @@ -1,52 +1,53 @@ #ifndef IMAPBASE_H #define IMAPBASE_H #include <qobject.h> #include "configfile.h" class QSocket; class IMAPBase : public QObject { Q_OBJECT public: IMAPBase(const Account &account); enum Error { IMAPErrConnectionRefused, IMAPErrHostNotFound, IMAPErrSocketRead, IMAPErrUnknownError, IMAPErrLoginFailed }; void sendCommand(const QString &command); void disconnect(); signals: void dataReceived(const QString &data); void lookingUpHost(); void hostFound(); void connected(); void disconnected(); void error(int err); protected: void makeConnect(); protected slots: void writeCommands(); void slotError(int error); void slotHostFound(); void slotConnected(); void slotDisconnected(); void slotDataAvailiable(); + void tryRead ( QString & ); private: Account _account; QString _data; QSocket *_socket; QStringList _commandQueue; bool _connected, _writingAllowed; - + QString _lasttag; }; #endif diff --git a/noncore/unsupported/mail2/libmail/imaphandler.cpp b/noncore/unsupported/mail2/libmail/imaphandler.cpp index 7493240..dc97b28 100644 --- a/noncore/unsupported/mail2/libmail/imaphandler.cpp +++ b/noncore/unsupported/mail2/libmail/imaphandler.cpp @@ -237,107 +237,110 @@ QString IMAPHandler::iStore(const QString &message, const QString &items) { doLogin(); _ibase->sendCommand(QString("%1 STORE %2 %3\r\n") .arg(tag()) .arg(message) .arg(items)); return tag(false); } QString IMAPHandler::iCopy(const QString &message, const QString &mailbox) { doLogin(); _ibase->sendCommand(QString("%1 COPY %2 \"%3\"\r\n") .arg(tag()) .arg(message) .arg(escape(mailbox))); return tag(false); } QString IMAPHandler::iUid(const QString &command, const QString &arguments) { doLogin(); _ibase->sendCommand(QString("%1 UID %2 %3\r\n") .arg(tag()) .arg(command) .arg(arguments)); return tag(false); } QString IMAPHandler::iX(const QString &commandAtom, const QString &arguments) { doLogin(); _ibase->sendCommand(QString("%1 X%2 %3\r\n") .arg(tag()) .arg(commandAtom) .arg(arguments)); return tag(false); } QString IMAPHandler::escape(const QString &in) { QString in_ = in; return in_.replace(QRegExp("\""), "\\\""); } QString IMAPHandler::tag(bool count) { return QString("a%1").arg(count ? _tag++ : _tag); } void IMAPHandler::slotDataReceived(const QString &data) { if (!_ready) { // The first data is always the greeting string. // We can ignore it. _ready = true; return; } - IMAPResponseParser parser(data); + IMAPResponseParser parser; +// connect ( &parser, SIGNAL( needMoreData ( QString & )), _ibase, SLOT( tryRead ( QString & ))); + parser. parse ( data ); IMAPResponse response = parser.response(); +// disconnect ( &parser, SIGNAL( needMoreData ( QString & )), _ibase, SLOT( tryRead ( QString & ))); response.setImapHandler(this); - if (!_loggingin) emit gotResponse(response); + if (!_loggingin) { qDebug("Emitting gotResponse!\n" ); emit gotResponse(response); } else { if (response.statusResponse().status() == IMAPResponseEnums::OK) { _loggingin = false; _loggedin = true; qWarning("OK. Logged in. Leaving loggingin state."); } else { _loggingin = false; emit IMAPError(IMAPBase::IMAPErrLoginFailed); } } } void IMAPHandler::slotLookingUpHost() { emit IMAPLookingUpHost(); } void IMAPHandler::slotHostFound() { emit IMAPHostFound(); } void IMAPHandler::slotConnected() { emit IMAPConnected(); } void IMAPHandler::slotDisconnected() { _loggedin = false; emit IMAPDisconnected(); } void IMAPHandler::slotError(int err) { emit IMAPError(err); } diff --git a/noncore/unsupported/mail2/libmail/imapresponse.cpp b/noncore/unsupported/mail2/libmail/imapresponse.cpp index 06dca33..ce5b18b 100644 --- a/noncore/unsupported/mail2/libmail/imapresponse.cpp +++ b/noncore/unsupported/mail2/libmail/imapresponse.cpp @@ -1,265 +1,311 @@ #include "imapresponse.h" -static QString _previousData; -static unsigned int _neededData; -IMAPResponseParser::IMAPResponseParser(const QString &data) +IMAPResponseParser::IMAPResponseParser() +{ +} + +void IMAPResponseParser::parse ( const QString &_data ) { - QString _data = data, more; - _data.replace((QString)"\r\n", "\n"); - - QStringList lines = QStringList::split('\n', _data); - QStringList::Iterator it; - for (it = lines.begin(); it != lines.end(); it++) { - QString tag, lineData; - - if (!_previousData.isNull()) { - qDebug(QString("IMAPResponseParser: got additional data. (%1/%2)").arg(_previousData.length()).arg(_neededData)); - _previousData += *it + "\n"; - if (_previousData.length() >= _neededData) { - _previousData += ")"; - qDebug("IMAPResponseParser: got ALL additional data."); - qDebug("Data is: " + _previousData); - parseResponse(_previousData); - _previousData = QString(0); - _neededData = 0; - } - } else { - splitTagData(*it, tag, lineData); - if (tag == "*") { - int pos; - if ((pos = data.find(QRegExp("\\{\\d*\\}"))) != -1) { - qDebug("IMAPResponseParser: waiting for additional data..."); - _previousData = lineData + "\n"; - - QString tmp = data.right(data.length() - pos - 1).stripWhiteSpace(); - tmp.truncate(tmp.length() - 1); - - _neededData = tmp.toUInt(); - if (_previousData.length() >= _neededData) { - qDebug("IMAPResponseParser: got ALL additional data. (1st)"); - parseResponse(_previousData); - _previousData = QString(0); - _neededData = 0; - } else { + QString data = _data; + + int pos = 0; + int len = data. length ( ); + + + while ( pos < len ) { + pos = data. find ( QRegExp ( "[^\\s]" ), pos ); + + if (( pos < 0 ) || ( pos >= len )) + break; + + switch ( data [pos]. latin1 ( )) { + case '*': { + qDebug ( "* ASTERIX\n" ); + + int eol = data. find ( '\n', pos ); + int bracket = data. findRev ( '{', eol ); + int rest = data. find ( QRegExp ( "[^\\s]" ), pos + 1 ); + + qDebug ( "pos=%d, rest=%d, bracket=%d, eol=%d\n", pos, rest, bracket, eol ); + + if ( bracket > pos ) { + uint needdata = data. mid ( bracket + 1, data. find ( '}', bracket + 1 ) - bracket - 1 ). toUInt ( ); + + if ( needdata ) { + qDebug ( "nd=%d - hd=%d\n", needdata, ( len - eol - 1 )); + + while ( needdata > ( len - eol - 1 )) { + qDebug ( "emitting need more...\n" ); + emit needMoreData ( data ); + len = data. length ( ); + } + qDebug ( "Got all data...\n" ); + + QString tmp = data. mid ( rest, eol - rest + 1 + needdata ); + + int tail = 0; + + while ( data [eol - rest + 1 + needdata + tail] != ')' ) + tail++; + tmp. append ( data. mid ( eol - rest + 1 + needdata, tail + 1 )); + + + qDebug ( "Complete parse = |%s|\n", tmp.latin1()); + + parseResponse ( tmp ); + + pos = rest + needdata + tail + 1; break; - } - } else { - parseResponse(lineData); + } } - } else if (tag == "+") { - emit needMoreData(_data); - } else { - _iresponse.setTag(tag); - parseResponse(_data, true); + + parseResponse ( data. mid ( rest, eol - rest + 1 ). stripWhiteSpace ( )); + break; + } + case '+': { + qDebug ( "+ PLUS\n" ); + + emit needMoreData ( data ); + len = data. length ( ); + break; + } + default : { + qDebug ( "OTHER: '%s...'\n", data. mid ( pos, 20 ). latin1 ( )); + + uint rest = data. find ( ' ', pos + 1 ); + rest = data. find ( QRegExp ( "[^\\s]" ), rest + 1 ); + _iresponse. setTag ( data. mid ( pos, rest - pos ). stripWhiteSpace ( )); + parseResponse ( data. mid ( rest, data. find ( '\n', rest )). stripWhiteSpace ( ), true ); + break; } } + + // skip to end-of-line + while (( pos < len ) && ( data [pos] != '\n' )) + pos++; } } + IMAPResponse IMAPResponseParser::response() { return _iresponse; } void IMAPResponseParser::parseResponse(const QString &data, bool tagged) { QString response, line; int pos; bool isNum = false; + + +// qDebug ( "\n\n#### PRD #### : #%s#\n\n", data.latin1()); + if ((pos = data.find(' ')) != -1) { response = data.left(pos).upper(); response.toInt(&isNum); line = data.right(data.length() - pos - 1); } else { - qWarning("IMAPResponseParser: parseResponse: No response found."); + qWarning("IMAPResponseParser: parseResponse: No response found."); return; } if (response == "OK" && tagged) { IMAPResponseStatusResponse status(OK, line); status.setResponseCode(getResponseCode(status.comment())); _iresponse.setStatusResponse(status); } else if (response == "OK" && !tagged) { IMAPResponseOK ok(line, getResponseCode(line)); _iresponse.addOK(ok); } else if (response == "NO" && tagged) { IMAPResponseStatusResponse status(NO, line); status.setResponseCode(getResponseCode(status.comment())); _iresponse.setStatusResponse(status); } else if (response == "NO" && !tagged) { IMAPResponseNO no(line, getResponseCode(line)); _iresponse.addNO(no); } else if (response == "BAD" && tagged) { IMAPResponseStatusResponse status(BAD, line); status.setResponseCode(getResponseCode(status.comment())); _iresponse.setStatusResponse(status); } else if (response == "BAD" && !tagged) { IMAPResponseBAD bad(line, getResponseCode(line)); _iresponse.addBAD(bad); } else if (response == "PREAUTH" && tagged) { IMAPResponseStatusResponse status(PREAUTH, line); _iresponse.setStatusResponse(status); } else if (response == "PREAUTH" && !tagged) { qDebug("IMAPResponseParser: responseParser: got untagged PREAUTH response."); // XXX } else if (response == "BYE") { IMAPResponseStatusResponse status(BYE, line); if (!tagged) status.setExitedUnexpected(true); _iresponse.setStatusResponse(status); } else if (response == "CAPABILITY") { IMAPResponseCAPABILITY capability(QStringList::split(' ', line)); _iresponse.addCAPABILITY(capability); } else if (response == "LIST") { QStringList list = splitData(line, true); QStringList flags; parseParenthesizedList(list[0], flags); removeLimiters(list[1]); removeLimiters(list[2]); IMAPResponseLIST rlist(parseFlagList(flags), list[1], list[2]); _iresponse.addLIST(rlist); } else if (response == "LSUB") { QStringList list = splitData(line, true); QStringList flags; parseParenthesizedList(list[0], flags); removeLimiters(list[1]); removeLimiters(list[2]); IMAPResponseLSUB lsub(parseFlagList(flags), list[1], list[2]); _iresponse.addLSUB(lsub); } else if (response == "STATUS") { QStringList list = splitData(line, true); removeLimiters(list[0]); IMAPResponseSTATUS status(list[0]); QStringList flags; parseParenthesizedList(list[1], flags); QStringList::Iterator it; for (it = flags.begin(); it != flags.end(); it++) { if (*it == "MESSAGES") status.setMessages(*(++it)); else if (*it == "RECENT") status.setRecent(*(++it)); else if (*it == "UIDNEXT") status.setUidnext(*(++it)); else if (*it == "UIDVALIDITY") status.setUidvalidity(*(++it)); else if (*it == "UNSEEN") status.setUnseen(*(++it)); - else qWarning("IMAPResponseParser: parseResponse: Unknown status data: " + *(it++) + "|"); + else qWarning((QString("IMAPResponseParser: parseResponse: Unknown status data: " )+ *(it++) + "|").latin1()); } _iresponse.addSTATUS(status); } else if (response == "SEARCH") { IMAPResponseSEARCH search(QStringList::split(' ', line)); _iresponse.addSEARCH(search); } else if (response == "FLAGS") { QStringList list; parseParenthesizedList(line, list); IMAPResponseFLAGS flags(parseFlagList(list)); _iresponse.addFLAGS(flags); } else if (isNum) { QStringList list = QStringList::split(' ', line); if (list[0] == "EXISTS") { IMAPResponseEXISTS exists(response); _iresponse.addEXISTS(exists); } else if (list[0] == "RECENT") { IMAPResponseRECENT recent(response); _iresponse.addRECENT(recent); } else if (list[0] == "EXPUNGE") { IMAPResponseEXPUNGE expunge(response); _iresponse.addEXPUNGE(expunge); } else if (list[0] == "FETCH") { IMAPResponseFETCH fetch; QStringList::Iterator it; + qDebug ( "Got FETCH\n" ); + QStringList fetchList = splitData(line, true); QStringList list; + + qDebug ( "fl [0]=%s, fl [1]=%s, fl[2]=%s\n", fetchList[0].latin1(),fetchList[1].latin1(),fetchList[2].latin1()); + parseParenthesizedList(fetchList[1], list); for (it = list.begin(); it != list.end(); it++) { + qDebug ( "Checking list[] == %s\n", (*it).latin1()); + if (*it == "BODY") { qDebug("IMAPResponseParser: responseParser: got FETCH::BODY"); // XXX - } else if ((*it).find(QRegExp("BODY\\[\\d+\\]")) != -1) { - QString bodydata = *(++it); + } else if ((*it).find(QRegExp("^BODY\\[\\d+\\]")) != -1) { qDebug("IMAPResponseParser: responseParser: got FETCH::BODY[x]"); - QStringList blist; - parseParenthesizedList(bodydata, blist); + QString number = ( *it ). mid ( 5, ( *it ). length ( ) - 6 ); + QString bodydata = *(++it); + +// QStringList blist; +// parseParenthesizedList(bodydata, blist); IMAPResponseBodyPart bodypart; - QString tmp; - for (unsigned int i = 2; i < blist.count(); i++) { - if (i != 2) tmp += " " + blist[i]; - else tmp += blist[i]; - } - bodypart.setData(tmp); +// QString tmp; +// for (unsigned int i = 2; i < blist.count(); i++) { +// if (i != 2) tmp += " " + blist[i]; +// else tmp += blist[i]; +// } + bodypart.setData(bodydata); + +// QString tmp = list[0]; +// tmp.replace(0, 5, ""); +// tmp.truncate(blist[0].length() - 1); + bodypart.setPart(number); - tmp = list[0]; - tmp.replace(0, 5, ""); - tmp.truncate(blist[0].length() - 1); - bodypart.setPart(tmp); + qDebug("added bodypart [%s]: '%s'\n\n", number.latin1(), bodydata.latin1()); fetch.addBodyPart(bodypart); } else if (*it == "BODYSTRUCTURE") { qDebug("IMAPResponseParser: responseParser: got FETCH::BODYSTRUCTURE"); /* QString bsdata = *(++it); QStringList bsList; parseParenthesizedList(bsdata, bsList); IMAPResponseBodystructure bodystructure; QStringList attachml; for (int i = 0; i < bsList.count() - 1; i++) { parseParenthesizedList(bsList[0], attachml); IMAPResponseBodypart bodypart; bodypart.setMimeTypeMain(attachml[0] == "NIL" ? QString(0) : attachml[0]); bodypart.setMimeTypeSub(attachml[1] == "NIL" ? QString(0) : attachml[1]); bodypart.setAddData(attachml[2] == "NIL" ? QString(0) : attachml[2]); // 3 (NIL) // 4 (NIL) bodypart.setEncoding(attachml[5] == "NIL" ? QString(0) : attachml[5]); bodypart.setSize(attachml[6] == "NIL" ? QString(0) : attachml[6]); bodypart.setLength(attachml[7] == "NIL" ? QString(0) : attachml[7]); bodypart.setAttachInfo(attachml[8] == "NIL" ? QString(0) : attachml[8]); // 9 (NIL) // 10 (NIL) bodystructure.addBodyPart(bodypart); } */ } else if (*it == "ENVELOPE") { QString envdata = *(++it); QStringList envList; parseParenthesizedList(envdata, envList); IMAPResponseEnvelope envelope; envelope.setMailDate(envList[0] == "NIL" ? QString(0) : removeLimiters(envList[0])); envelope.setSubject(envList[1] == "NIL" ? QString(0) : removeLimiters(envList[1])); QStringList froml, senderl, replytol, tol, ccl, bccl; QStringList froma, sendera, replytoa, toa, cca, bcca; parseParenthesizedList(envList[2], froml); parseParenthesizedList(envList[3], senderl); parseParenthesizedList(envList[4], replytol); parseParenthesizedList(envList[5], tol); parseParenthesizedList(envList[6], ccl); parseParenthesizedList(envList[7], bccl); QStringList::Iterator it; for (it = froml.begin(); it != froml.end(); it++) { parseParenthesizedList(*it, froma); if (froml[0] != "NIL") envelope.addFrom(IMAPResponseAddress( removeLimiters(froma[0]), removeLimiters(froma[1]), removeLimiters(froma[2]), removeLimiters(froma[3]))); } for (it = senderl.begin(); it != senderl.end(); it++) { parseParenthesizedList(*it, sendera); if (senderl[0] != "NIL") envelope.addSender(IMAPResponseAddress( @@ -276,173 +322,205 @@ void IMAPResponseParser::parseResponse(const QString &data, bool tagged) removeLimiters(replytoa[0]), removeLimiters(replytoa[1]), removeLimiters(replytoa[2]), removeLimiters(replytoa[3]))); } for (it = tol.begin(); it != tol.end(); it++) { parseParenthesizedList(*it, toa); if (tol[0] != "NIL") envelope.addTo(IMAPResponseAddress( removeLimiters(toa[0]), removeLimiters(toa[1]), removeLimiters(toa[2]), removeLimiters(toa[3]))); } for (it = ccl.begin(); it != ccl.end(); it++) { parseParenthesizedList(*it, cca); if (ccl[0] != "NIL") envelope.addCc(IMAPResponseAddress( removeLimiters(cca[0]), removeLimiters(cca[1]), removeLimiters(cca[2]), removeLimiters(cca[3]))); } for (it = bccl.begin(); it != bccl.end(); it++) { parseParenthesizedList(*it, bcca); if (bccl[0] != "NIL") envelope.addBcc(IMAPResponseAddress( removeLimiters(bcca[0]), removeLimiters(bcca[1]), removeLimiters(bcca[2]), removeLimiters(bcca[3]))); } envelope.setInReplyTo(envList[7] == "NIL" ? QString(0) : removeLimiters(envList[7])); envelope.setMessageId(envList[8] == "NIL" ? QString(0) : removeLimiters(envList[8])); fetch.setEnvelope(envelope); } else if (*it == "FLAGS") { QString flagdata = *(++it); QStringList flags; parseParenthesizedList(flagdata, flags); fetch.setFlags(parseFlagList(flags)); } else if (*it == "INTERNALDATE") { fetch.setInternalDate(removeLimiters(*(++it))); } else if (*it == "RFC822" || *it == "BODY[]") { qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822"); // XXX } else if (*it == "RFC822.HEADER" || *it == "BODY.PEEK[HEADER]") { qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822.HEADER"); // XXX } else if (*it == "RFC822.SIZE") { fetch.setRFC822Size(*(++it)); } else if (*it == "RFC822.TEXT" || *it == "BODY[TEXT]") { qDebug("IMAPResponseParser: responseParser: got FETCH::RFC822.TEXT"); // XXX } else if (*it == "UID") { fetch.setUid(*(++it)); } } _iresponse.addFETCH(fetch); } - } else qWarning("IMAPResponseParser: parseResponse: Unknown response: " + response + "|"); + } else qWarning((QString("IMAPResponseParser: parseResponse: Unknown response: ") + response + "|").latin1()); + } QStringList IMAPResponseParser::splitData(const QString &data, bool withBrackets) { int b = 0; bool a = false, noappend = false, escaped = false; QString temp; QStringList list; + qDebug ( "sd: '%s'\n", data.latin1()); + for (unsigned int i = 0; i <= data.length(); i++) { if (withBrackets && data[i] == '(' && !a) b++; else if (withBrackets && data[i] == ')' && !a) b--; - if (data[i] == '"' && !escaped) a = !a; + if (data[i] == '{' && !escaped && !a ) { + qDebug ( "sd: found a {\n" ); + + int p = data. find ( '}', i + 1 ); + int eol = data. find ( '\n', i + 1 ); + + if ( p > int( i )) { + int len = data. mid ( i + 1, p - i - 1 ). toInt ( ); + + qDebug ( "sd: skipping %d bytes\n", len ); + + if ( b == 0 ) { + temp = data. mid ( eol + 1, len ); + noappend = false; + i = eol + len; + continue; + } + else { + temp. append ( '{' ); + temp. append ( QString::number ( len )); + temp. append ( "}\r\n" ); + temp. append ( data. mid ( eol + 1, len )); + i = eol + len; + continue; + } + } + } + + if (data[i] == '\"' && !escaped) a = !a; else escaped = false; - if (data[i] == '\\' && data[i + 1] == '"') escaped = true; + if (data[i] == '\\' && data[i + 1] == '\"') escaped = true; if ((data[i] == ' ' || i == data.length()) && b == 0 && !a) { list.append(temp); - temp = QString(0); + temp = QString::null; if (data[i] == ' ') noappend = true; } if (!noappend) temp += data[i]; noappend = false; } return list; } void IMAPResponseParser::parseParenthesizedList(const QString &data, QStringList &parsed) { QString data_(data); removeLimiters(data_, '(', ')'); parsed = splitData(data_, true); } void IMAPResponseParser::splitTagData(const QString &line, QString &tag, QString &data) { int pos; if ((pos = line.find(' ')) != -1) { tag = line.left(pos); data = line.right(line.length() - pos - 1); - } else qWarning("IMAPResponseParser: splitTagData: tag not found. Line was " + line + "|"); + } else qWarning((QString("IMAPResponseParser: splitTagData: tag not found. Line was ") + line + "|").latin1()); } QString IMAPResponseParser::removeLimiters(QString &string, const QChar &sl, const QChar &el) { QString tmpString; + string = string. stripWhiteSpace ( ); + if (string[0] == sl && string[string.length() - 1] == el) { string.truncate(string.length() - 1); string.replace(0, 1, ""); for (unsigned int i = 1; i <= string.length(); i++) { - if (string[i - 1] == '\\' && sl == '"') ++i; + if (string[i - 1] == '\\' && sl == '\"') ++i; tmpString += string[i - 1]; } } - return tmpString; } IMAPResponseEnums::IMAPResponseCode IMAPResponseParser::getResponseCode(const QString &line) { if (line.find(QRegExp((QString) "^\\[.*\\]" + ' ' + ".*")) != -1) { int pos = line.find("] "); QString code = line.left(pos + 1).upper(); if (code.find(QRegExp("[ALERT]")) != -1) return ALERT; else if (code.find(QRegExp("[NEWNAME .* .*]")) != -1) return NEWNAME; // XXX else if (code.find(QRegExp("[PARSE]")) != -1) return PARSE; else if (code.find(QRegExp("[PERMANENTFLAGS \\d*]")) != -1) return PERMANENTFLAGS; // XXX else if (code.find(QRegExp("[READ-ONLY]")) != -1) return READONLY; else if (code.find(QRegExp("[READ-WRITE]")) != -1) return READWRITE; else if (code.find(QRegExp("[TRYCREATE]")) != -1) return TRYCREATE; else if (code.find(QRegExp("[UIDVALIDITY \\d*]")) != -1) return UIDVALIDITY; // XXX else if (code.find(QRegExp("[UNSEEN \\d*]")) != -1) return UNSEEN; // XXX else { - qWarning("IMAPResponseParser: getResponseCode: Unknown code: " + code + "|"); + qWarning((QString("IMAPResponseParser: getResponseCode: Unknown code: ") + code + "|").latin1()); return UnknownCode; } } return NoCode; } QValueList<IMAPResponseEnums::IMAPResponseFlags> IMAPResponseParser::parseFlagList(const QStringList &flagList) { QValueList<IMAPResponseFlags> flags; QStringList::ConstIterator it; for (it = flagList.begin(); it != flagList.end(); it++) { QString flag = (*it).lower(); if (flag == "\\seen") flags.append(Seen); else if (flag == "\\answered") flags.append(Answered); else if (flag == "\\flagged") flags.append(Flagged); else if (flag == "\\deleted") flags.append(Deleted); else if (flag == "\\draft") flags.append(Draft); else if (flag == "\\recent") flags.append(Recent); else if (flag == "\\noinferiors") flags.append(Noinferiors); else if (flag == "\\noselect") flags.append(Noselect); else if (flag == "\\marked") flags.append(Marked); else if (flag == "\\unmarked") flags.append(Unmarked); else if (flag.isEmpty()) { } - else qWarning("IMAPResponseParser: parseFlagList: Unknown flag: " + *it + "|"); + else qWarning((QString("IMAPResponseParser: parseFlagList: Unknown flag: ") + *it + "|").latin1()); } return flags; } diff --git a/noncore/unsupported/mail2/libmail/imapresponse.h b/noncore/unsupported/mail2/libmail/imapresponse.h index 73435ee..5a19b96 100644 --- a/noncore/unsupported/mail2/libmail/imapresponse.h +++ b/noncore/unsupported/mail2/libmail/imapresponse.h @@ -444,88 +444,89 @@ public: void setTag(QString tag) { _tag = tag; } QString tag() { return _tag; } void setImapHandler(IMAPHandler *handler) { _handler = handler; } IMAPHandler *imapHandler() { return _handler; } void setStatusResponse(IMAPResponseStatusResponse response) { _response = response; } IMAPResponseStatusResponse statusResponse() { return _response; } void addOK(IMAPResponseOK ok) { _okl.append(ok); } void addNO(IMAPResponseNO no) { _nol.append(no); } void addBAD(IMAPResponseBAD bad) { _badl.append(bad); } void addCAPABILITY(IMAPResponseCAPABILITY capability) { _capabilityl.append(capability); } void addLIST(IMAPResponseLIST list) { _listl.append(list); } void addLSUB(IMAPResponseLSUB lsub) { _lsubl.append(lsub); } void addSTATUS(IMAPResponseSTATUS status) { _statusl.append(status); } void addSEARCH(IMAPResponseSEARCH search) { _searchl.append(search); } void addFLAGS(IMAPResponseFLAGS flags) { _flagsl.append(flags); } void addEXISTS(IMAPResponseEXISTS exists) { _existsl.append(exists); } void addRECENT(IMAPResponseRECENT recent) { _recentl.append(recent); } void addEXPUNGE(IMAPResponseEXPUNGE expunge) { _expungel.append(expunge); } void addFETCH(IMAPResponseFETCH fetch) { _fetchl.append(fetch); } QValueList<IMAPResponseOK> OK() { return _okl; } QValueList<IMAPResponseNO> NO() { return _nol; } QValueList<IMAPResponseBAD> BAD() { return _badl; } QValueList<IMAPResponseCAPABILITY> CAPABILITY() { return _capabilityl; } QValueList<IMAPResponseLIST> LIST() { return _listl; } QValueList<IMAPResponseLSUB> LSUB() { return _lsubl; } QValueList<IMAPResponseSTATUS> STATUS() { return _statusl; } QValueList<IMAPResponseSEARCH> SEARCH() { return _searchl; } QValueList<IMAPResponseFLAGS> FLAGS() { return _flagsl; } QValueList<IMAPResponseEXISTS> EXISTS() { return _existsl; } QValueList<IMAPResponseRECENT> RECENT() { return _recentl; } QValueList<IMAPResponseEXPUNGE> EXPUNGE() { return _expungel; } QValueList<IMAPResponseFETCH> FETCH() { return _fetchl; } private: QString _tag; IMAPResponseStatusResponse _response; IMAPHandler *_handler; QValueList<IMAPResponseOK> _okl; QValueList<IMAPResponseNO> _nol; QValueList<IMAPResponseBAD> _badl; QValueList<IMAPResponseCAPABILITY> _capabilityl; QValueList<IMAPResponseLIST> _listl; QValueList<IMAPResponseLSUB> _lsubl; QValueList<IMAPResponseSTATUS> _statusl; QValueList<IMAPResponseSEARCH> _searchl; QValueList<IMAPResponseFLAGS> _flagsl; QValueList<IMAPResponseEXISTS> _existsl; QValueList<IMAPResponseRECENT> _recentl; QValueList<IMAPResponseEXPUNGE> _expungel; QValueList<IMAPResponseFETCH> _fetchl; }; class IMAPResponseParser : public QObject, public IMAPResponseEnums { Q_OBJECT public: - IMAPResponseParser(const QString &data); + IMAPResponseParser(); + void parse ( const QString &data); IMAPResponse response(); signals: - void needMoreData(const QString &comment); + void needMoreData(QString &data); protected: void parseResponse(const QString &data, bool tagged = false); QStringList splitData(const QString &data, bool withBrackets); void parseParenthesizedList(const QString &data, QStringList &parsed); void splitTagData(const QString &line, QString &tag, QString &data); QString removeLimiters(QString &string, const QChar &sl = '"', const QChar &el = '"'); IMAPResponseCode getResponseCode(const QString &line); QValueList<IMAPResponseFlags> parseFlagList(const QStringList &flags); private: IMAPResponse _iresponse; }; #endif diff --git a/noncore/unsupported/mail2/viewmail.cpp b/noncore/unsupported/mail2/viewmail.cpp index 3c88d99..da6924d 100644 --- a/noncore/unsupported/mail2/viewmail.cpp +++ b/noncore/unsupported/mail2/viewmail.cpp @@ -122,77 +122,77 @@ void ViewMail::slotReply() else prefix = "Re: "; // no i18n on purpose SendMail sendMail; sendMail.setTo(_mail.envelope().from()[0].toString()); sendMail.setSubject(prefix + _mail.envelope().subject()); sendMail.setInReplyTo(_mail.envelope().messageId()); sendMail.setMessage(rtext); Composer composer(this, 0, true); composer.setSendMail(sendMail); composer.showMaximized(); composer.exec(); } void ViewMail::slotForward() { if (!_gotBody) { QMessageBox::information(this, tr("Error"), tr("<p>The mail body is not yet downloaded, so you cannot forward yet."), tr("Ok")); return; } QString ftext; ftext += QString("\n----- Forwarded message from %1 -----\n\n") .arg(_mail.envelope().from()[0].toString()); if (!_mail.envelope().mailDate().isNull()) ftext += QString("Date: %1\n") .arg(_mail.envelope().mailDate()); if (!_mail.envelope().from()[0].toString().isNull()) ftext += QString("From: %1\n") .arg(_mail.envelope().from()[0].toString()); if (!_mail.envelope().to().toString().isNull()) ftext += QString("To: %1\n") .arg(_mail.envelope().to().toString()); if (!_mail.envelope().cc().toString().isNull()) ftext += QString("Cc: %1\n") .arg(_mail.envelope().cc().toString()); if (!_mail.envelope().bcc().toString().isNull()) ftext += QString("Bcc: %1\n") .arg(_mail.envelope().bcc().toString()); if (!_mail.envelope().subject().isNull()) ftext += QString("Subject: %1\n") .arg(_mail.envelope().subject()); ftext += QString("\n%1\n") .arg(_mail.bodyPart(1).data()); ftext += QString("----- End forwarded message -----\n"); SendMail sendMail; sendMail.setSubject("Fwd: " + _mail.envelope().subject()); sendMail.setMessage(ftext); Composer composer(this, 0, true); composer.setSendMail(sendMail); composer.showMaximized(); composer.exec(); } void ViewMail::slotIMAPUid(IMAPResponse &response) { disconnect(_handler, SIGNAL(gotResponse(IMAPResponse &)), this, SLOT(slotIMAPUid(IMAPResponse &))); if (response.statusResponse().status() == IMAPResponseEnums::OK) { QValueList<IMAPResponseBodyPart> bodyParts; - bodyParts.append(response.FETCH()[0].bodyPart(1)); + bodyParts.append(response.FETCH()[0].bodyPart(0)); _mail.setBodyParts(bodyParts); - browser->setText(QString(_mailHtml).arg(deHtml(response.FETCH()[0].bodyPart(1).data()))); + browser->setText(QString(_mailHtml).arg(deHtml(response.FETCH()[0].bodyPart(0).data()))); // fillList(response.FETCH()[0].bodyStructure()); _gotBody = true; } else { QMessageBox::warning(this, tr("Error"), tr("<p>I was unable to retrieve the mail from the server. You can try again later or give up.</p>"), tr("Ok")); } } |