diff options
Diffstat (limited to 'tdeioslaves/imap4/imapparser.cc')
-rw-r--r-- | tdeioslaves/imap4/imapparser.cc | 2094 |
1 files changed, 0 insertions, 2094 deletions
diff --git a/tdeioslaves/imap4/imapparser.cc b/tdeioslaves/imap4/imapparser.cc deleted file mode 100644 index 8cb06e318..000000000 --- a/tdeioslaves/imap4/imapparser.cc +++ /dev/null @@ -1,2094 +0,0 @@ -/********************************************************************** - * - * imapparser.cc - IMAP4rev1 Parser - * Copyright (C) 2001-2002 Michael Haeckel <haeckel@kde.org> - * Copyright (C) 2000 s.carstens@gmx.de - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Send comments and bug fixes to s.carstens@gmx.de - * - *********************************************************************/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "rfcdecoder.h" - -#include "imapparser.h" - -#include "imapinfo.h" - -#include "mailheader.h" -#include "mimeheader.h" -#include "mailaddress.h" - -#include <sys/types.h> - -#include <stdlib.h> -#include <unistd.h> - -#ifdef HAVE_LIBSASL2 -extern "C" { -#include <sasl/sasl.h> -} -#endif - -#include <tqregexp.h> -#include <tqbuffer.h> -#include <tqstring.h> -#include <tqstringlist.h> - -#include <kdebug.h> -#include <kmdcodec.h> -#include <kurl.h> - -#include <kasciistricmp.h> -#include <kasciistringtools.h> - -#ifdef HAVE_LIBSASL2 -static sasl_callback_t callbacks[] = { - { SASL_CB_ECHOPROMPT, NULL, NULL }, - { SASL_CB_NOECHOPROMPT, NULL, NULL }, - { SASL_CB_GETREALM, NULL, NULL }, - { SASL_CB_USER, NULL, NULL }, - { SASL_CB_AUTHNAME, NULL, NULL }, - { SASL_CB_PASS, NULL, NULL }, - { SASL_CB_CANON_USER, NULL, NULL }, - { SASL_CB_LIST_END, NULL, NULL } -}; -#endif - -imapParser::imapParser () -{ - sentQueue.setAutoDelete (false); - completeQueue.setAutoDelete (true); - currentState = ISTATE_NO; - commandCounter = 0; - lastHandled = 0; -} - -imapParser::~imapParser () -{ - delete lastHandled; - lastHandled = 0; -} - -imapCommand * -imapParser::doCommand (imapCommand * aCmd) -{ - int pl = 0; - sendCommand (aCmd); - while (pl != -1 && !aCmd->isComplete ()) { - while ((pl = parseLoop ()) == 0) - ; - } - - return aCmd; -} - -imapCommand * -imapParser::sendCommand (imapCommand * aCmd) -{ - aCmd->setId (TQString::number(commandCounter++)); - sentQueue.append (aCmd); - - continuation.resize(0); - const TQString& command = aCmd->command(); - - if (command == "SELECT" || command == "EXAMINE") - { - // we need to know which box we are selecting - parseString p; - p.fromString(aCmd->parameter()); - currentBox = parseOneWordC(p); - kdDebug(7116) << "imapParser::sendCommand - setting current box to " << currentBox << endl; - } - else if (command == "CLOSE") - { - // we no longer have a box open - currentBox = TQString(); - } - else if (command.find ("SEARCH") != -1 - || command == "GETACL" - || command == "LISTRIGHTS" - || command == "MYRIGHTS" - || command == "GETANNOTATION" - || command == "NAMESPACE" - || command == "GETQUOTAROOT" - || command == "GETQUOTA" - || command == "X-GET-OTHER-USERS" - || command == "X-GET-DELEGATES" - || command == "X-GET-OUT-OF-OFFICE") - { - lastResults.clear (); - } - else if (command == "LIST" - || command == "LSUB") - { - listResponses.clear (); - } - parseWriteLine (aCmd->getStr ()); - return aCmd; -} - -bool -imapParser::clientLogin (const TQString & aUser, const TQString & aPass, - TQString & resultInfo) -{ - imapCommand *cmd; - bool retVal = false; - - cmd = - doCommand (new - imapCommand ("LOGIN", "\"" + rfcDecoder::quoteIMAP(aUser) - + "\" \"" + rfcDecoder::quoteIMAP(aPass) + "\"")); - - if (cmd->result () == "OK") - { - currentState = ISTATE_LOGIN; - retVal = true; - } - resultInfo = cmd->resultInfo(); - completeQueue.removeRef (cmd); - - return retVal; -} - -#ifdef HAVE_LIBSASL2 -static bool sasl_interact( TDEIO::SlaveBase *slave, TDEIO::AuthInfo &ai, void *in ) -{ - kdDebug(7116) << "sasl_interact" << endl; - sasl_interact_t *interact = ( sasl_interact_t * ) in; - - //some mechanisms do not require username && pass, so it doesn't need a popup - //window for getting this info - for ( ; interact->id != SASL_CB_LIST_END; interact++ ) { - if ( interact->id == SASL_CB_AUTHNAME || - interact->id == SASL_CB_PASS ) { - - if ( ai.username.isEmpty() || ai.password.isEmpty() ) { - if (!slave->openPassDlg(ai)) - return false; - } - break; - } - } - - interact = ( sasl_interact_t * ) in; - while( interact->id != SASL_CB_LIST_END ) { - kdDebug(7116) << "SASL_INTERACT id: " << interact->id << endl; - switch( interact->id ) { - case SASL_CB_USER: - case SASL_CB_AUTHNAME: - kdDebug(7116) << "SASL_CB_[USER|AUTHNAME]: '" << ai.username << "'" << endl; - interact->result = strdup( ai.username.utf8() ); - interact->len = strlen( (const char *) interact->result ); - break; - case SASL_CB_PASS: - kdDebug(7116) << "SASL_CB_PASS: [hidden] " << endl; - interact->result = strdup( ai.password.utf8() ); - interact->len = strlen( (const char *) interact->result ); - break; - default: - interact->result = 0; - interact->len = 0; - break; - } - interact++; - } - return true; -} -#endif - -bool -imapParser::clientAuthenticate ( TDEIO::SlaveBase *slave, TDEIO::AuthInfo &ai, - const TQString & aFTQDN, const TQString & aAuth, bool isSSL, TQString & resultInfo) -{ - bool retVal = false; -#ifdef HAVE_LIBSASL2 - int result; - sasl_conn_t *conn = 0; - sasl_interact_t *client_interact = 0; - const char *out = 0; - uint outlen = 0; - const char *mechusing = 0; - TQByteArray tmp, challenge; - - kdDebug(7116) << "aAuth: " << aAuth << " FTQDN: " << aFTQDN << " isSSL: " << isSSL << endl; - - // see if server supports this authenticator - if (!hasCapability ("AUTH=" + aAuth)) - return false; - -// result = sasl_client_new( isSSL ? "imaps" : "imap", - result = sasl_client_new( "imap", /* FIXME: with cyrus-imapd, even imaps' digest-uri - must be 'imap'. I don't know if it's good or bad. */ - aFTQDN.latin1(), - 0, 0, callbacks, 0, &conn ); - - if ( result != SASL_OK ) { - kdDebug(7116) << "sasl_client_new failed with: " << result << endl; - resultInfo = TQString::fromUtf8( sasl_errdetail( conn ) ); - return false; - } - - do { - result = sasl_client_start(conn, aAuth.latin1(), &client_interact, - hasCapability("SASL-IR") ? &out : 0, &outlen, &mechusing); - - if ( result == SASL_INTERACT ) { - if ( !sasl_interact( slave, ai, client_interact ) ) { - sasl_dispose( &conn ); - return false; - } - } - } while ( result == SASL_INTERACT ); - - if ( result != SASL_CONTINUE && result != SASL_OK ) { - kdDebug(7116) << "sasl_client_start failed with: " << result << endl; - resultInfo = TQString::fromUtf8( sasl_errdetail( conn ) ); - sasl_dispose( &conn ); - return false; - } - imapCommand *cmd; - - tmp.setRawData( out, outlen ); - KCodecs::base64Encode( tmp, challenge ); - tmp.resetRawData( out, outlen ); - // then lets try it - TQString firstCommand = aAuth; - if ( !challenge.isEmpty() ) { - firstCommand += " "; - firstCommand += TQString::fromLatin1( challenge.data(), challenge.size() ); - } - cmd = sendCommand (new imapCommand ("AUTHENTICATE", firstCommand.latin1())); - - int pl = 0; - while ( pl != -1 && !cmd->isComplete () ) - { - //read the next line - while ((pl = parseLoop()) == 0) ; - - if (!continuation.isEmpty()) - { -// kdDebug(7116) << "S: " << TQCString(continuation.data(),continuation.size()+1) << endl; - if ( continuation.size() > 4 ) { - tmp.setRawData( continuation.data() + 2, continuation.size() - 4 ); - KCodecs::base64Decode( tmp, challenge ); -// kdDebug(7116) << "S-1: " << TQCString(challenge.data(),challenge.size()+1) << endl; - tmp.resetRawData( continuation.data() + 2, continuation.size() - 4 ); - } - - do { - result = sasl_client_step(conn, challenge.isEmpty() ? 0 : challenge.data(), - challenge.size(), - &client_interact, - &out, &outlen); - - if (result == SASL_INTERACT) { - if ( !sasl_interact( slave, ai, client_interact ) ) { - sasl_dispose( &conn ); - return false; - } - } - } while ( result == SASL_INTERACT ); - - if ( result != SASL_CONTINUE && result != SASL_OK ) { - kdDebug(7116) << "sasl_client_step failed with: " << result << endl; - resultInfo = TQString::fromUtf8( sasl_errdetail( conn ) ); - sasl_dispose( &conn ); - return false; - } - - tmp.setRawData( out, outlen ); -// kdDebug(7116) << "C-1: " << TQCString(tmp.data(),tmp.size()+1) << endl; - KCodecs::base64Encode( tmp, challenge ); - tmp.resetRawData( out, outlen ); -// kdDebug(7116) << "C: " << TQCString(challenge.data(),challenge.size()+1) << endl; - parseWriteLine (challenge); - continuation.resize(0); - } - } - - if (cmd->result () == "OK") - { - currentState = ISTATE_LOGIN; - retVal = true; - } - resultInfo = cmd->resultInfo(); - completeQueue.removeRef (cmd); - - sasl_dispose( &conn ); //we don't use sasl_en/decode(), so it's safe to dispose the connection. -#endif //HAVE_LIBSASL2 - return retVal; -} - -void -imapParser::parseUntagged (parseString & result) -{ - //kdDebug(7116) << "imapParser::parseUntagged - '" << result.cstr() << "'" << endl; - - parseOneWordC(result); // * - TQByteArray what = parseLiteral (result); // see whats coming next - - if(!what.isEmpty ()) { - switch (what[0]) - { - //the status responses - case 'B': // BAD or BYE - if (tqstrncmp(what, "BAD", what.size()) == 0) - { - parseResult (what, result); - } - else if (tqstrncmp(what, "BYE", what.size()) == 0) - { - parseResult (what, result); - if ( sentQueue.count() ) { - // BYE that interrupts a command -> copy the reason for it - imapCommand *current = sentQueue.at (0); - current->setResultInfo(result.cstr()); - } - currentState = ISTATE_NO; - } - break; - - case 'N': // NO - if (what[1] == 'O' && what.size() == 2) - { - parseResult (what, result); - } - else if (tqstrncmp(what, "NAMESPACE", what.size()) == 0) - { - parseNamespace (result); - } - break; - - case 'O': // OK - if (what[1] == 'K' && what.size() == 2) - { - parseResult (what, result); - } else if (tqstrncmp(what, "OTHER-USER", 10) == 0) { // X-GET-OTHER-USER - parseOtherUser (result); - } else if (tqstrncmp(what, "OUT-OF-OFFICE", 13) == 0) { // X-GET-OUT-OF-OFFICE - parseOutOfOffice (result); - } - break; - case 'D': - if (tqstrncmp(what, "DELEGATE", 8) == 0) { // X-GET-DELEGATES - parseDelegate (result); - } - break; - - case 'P': // PREAUTH - if (tqstrncmp(what, "PREAUTH", what.size()) == 0) - { - parseResult (what, result); - currentState = ISTATE_LOGIN; - } - break; - - // parse the other responses - case 'C': // CAPABILITY - if (tqstrncmp(what, "CAPABILITY", what.size()) == 0) - { - parseCapability (result); - } - break; - - case 'F': // FLAGS - if (tqstrncmp(what, "FLAGS", what.size()) == 0) - { - parseFlags (result); - } - break; - - case 'L': // LIST or LSUB or LISTRIGHTS - if (tqstrncmp(what, "LIST", what.size()) == 0) - { - parseList (result); - } - else if (tqstrncmp(what, "LSUB", what.size()) == 0) - { - parseLsub (result); - } - else if (tqstrncmp(what, "LISTRIGHTS", what.size()) == 0) - { - parseListRights (result); - } - break; - - case 'M': // MYRIGHTS - if (tqstrncmp(what, "MYRIGHTS", what.size()) == 0) - { - parseMyRights (result); - } - break; - case 'S': // SEARCH or STATUS - if (tqstrncmp(what, "SEARCH", what.size()) == 0) - { - parseSearch (result); - } - else if (tqstrncmp(what, "STATUS", what.size()) == 0) - { - parsetStatus (result); - } - break; - - case 'A': // ACL or ANNOTATION - if (tqstrncmp(what, "ACL", what.size()) == 0) - { - parseAcl (result); - } - else if (tqstrncmp(what, "ANNOTATION", what.size()) == 0) - { - parseAnnotation (result); - } - break; - case 'Q': // QUOTA or QUOTAROOT - if ( what.size() > 5 && tqstrncmp(what, "QUOTAROOT", what.size()) == 0) - { - parseQuotaRoot( result ); - } - else if (tqstrncmp(what, "QUOTA", what.size()) == 0) - { - parseQuota( result ); - } - break; - case 'X': // Custom command - { - parseCustom( result ); - } - break; - default: - //better be a number - { - ulong number; - bool valid; - - number = TQCString(what, what.size() + 1).toUInt(&valid); - if (valid) - { - what = parseLiteral (result); - if(!what.isEmpty ()) { - switch (what[0]) - { - case 'E': - if (tqstrncmp(what, "EXISTS", what.size()) == 0) - { - parseExists (number, result); - } - else if (tqstrncmp(what, "EXPUNGE", what.size()) == 0) - { - parseExpunge (number, result); - } - break; - - case 'F': - if (tqstrncmp(what, "FETCH", what.size()) == 0) - { - seenUid = TQString(); - parseFetch (number, result); - } - break; - - case 'S': - if (tqstrncmp(what, "STORE", what.size()) == 0) // deprecated store - { - seenUid = TQString(); - parseFetch (number, result); - } - break; - - case 'R': - if (tqstrncmp(what, "RECENT", what.size()) == 0) - { - parseRecent (number, result); - } - break; - default: - break; - } - } - } - } - break; - } //switch - } -} //func - - -void -imapParser::parseResult (TQByteArray & result, parseString & rest, - const TQString & command) -{ - if (command == "SELECT") - selectInfo.setReadWrite(true); - - if (rest[0] == '[') - { - rest.pos++; - TQCString option = parseOneWordC(rest, TRUE); - - switch (option[0]) - { - case 'A': // ALERT - if (option == "ALERT") - { - rest.pos = rest.data.find(']', rest.pos) + 1; - // The alert text is after [ALERT]. - // Is this correct or do we need to care about litterals? - selectInfo.setAlert( rest.cstr() ); - } - break; - - case 'N': // NEWNAME - if (option == "NEWNAME") - { - } - break; - - case 'P': //PARSE or PERMANENTFLAGS - if (option == "PARSE") - { - } - else if (option == "PERMANENTFLAGS") - { - uint end = rest.data.find(']', rest.pos); - TQCString flags(rest.data.data() + rest.pos, end - rest.pos); - selectInfo.setPermanentFlags (flags); - rest.pos = end; - } - break; - - case 'R': //READ-ONLY or READ-WRITE - if (option == "READ-ONLY") - { - selectInfo.setReadWrite (false); - } - else if (option == "READ-WRITE") - { - selectInfo.setReadWrite (true); - } - break; - - case 'T': //TRYCREATE - if (option == "TRYCREATE") - { - } - break; - - case 'U': //UIDVALIDITY or UNSEEN - if (option == "UIDVALIDITY") - { - ulong value; - if (parseOneNumber (rest, value)) - selectInfo.setUidValidity (value); - } - else if (option == "UNSEEN") - { - ulong value; - if (parseOneNumber (rest, value)) - selectInfo.setUnseen (value); - } - else if (option == "UIDNEXT") - { - ulong value; - if (parseOneNumber (rest, value)) - selectInfo.setUidNext (value); - } - else - break; - - } - if (rest[0] == ']') - rest.pos++; //tie off ] - skipWS (rest); - } - - if (command.isEmpty()) - { - // This happens when parsing an intermediate result line (those that start with '*'). - // No state change involved, so we can stop here. - return; - } - - switch (command[0].latin1 ()) - { - case 'A': - if (command == "AUTHENTICATE") - if (tqstrncmp(result, "OK", result.size()) == 0) - currentState = ISTATE_LOGIN; - break; - - case 'L': - if (command == "LOGIN") - if (tqstrncmp(result, "OK", result.size()) == 0) - currentState = ISTATE_LOGIN; - break; - - case 'E': - if (command == "EXAMINE") - { - if (tqstrncmp(result, "OK", result.size()) == 0) - currentState = ISTATE_SELECT; - else - { - if (currentState == ISTATE_SELECT) - currentState = ISTATE_LOGIN; - currentBox = TQString(); - } - kdDebug(7116) << "imapParser::parseResult - current box is now " << currentBox << endl; - } - break; - - case 'S': - if (command == "SELECT") - { - if (tqstrncmp(result, "OK", result.size()) == 0) - currentState = ISTATE_SELECT; - else - { - if (currentState == ISTATE_SELECT) - currentState = ISTATE_LOGIN; - currentBox = TQString(); - } - kdDebug(7116) << "imapParser::parseResult - current box is now " << currentBox << endl; - } - break; - - default: - break; - } - -} - -void imapParser::parseCapability (parseString & result) -{ - TQCString temp( result.cstr() ); - imapCapabilities = TQStringList::split ( ' ', KPIM::kAsciiToLower( temp.data() ) ); -} - -void imapParser::parseFlags (parseString & result) -{ - selectInfo.setFlags(result.cstr()); -} - -void imapParser::parseList (parseString & result) -{ - imapList this_one; - - if (result[0] != '(') - return; //not proper format for us - - result.pos++; // tie off ( - - this_one.parseAttributes( result ); - - result.pos++; // tie off ) - skipWS (result); - - this_one.setHierarchyDelimiter(parseLiteralC(result)); - this_one.setName (rfcDecoder::fromIMAP(parseLiteralC(result))); // decode modified UTF7 - - listResponses.append (this_one); -} - -void imapParser::parseLsub (parseString & result) -{ - imapList this_one (result.cstr(), *this); - listResponses.append (this_one); -} - -void imapParser::parseListRights (parseString & result) -{ - parseOneWordC (result); // skip mailbox name - parseOneWordC (result); // skip user id - int outlen = 1; - while ( outlen ) { - TQCString word = parseOneWordC (result, false, &outlen); - lastResults.append (word); - } -} - -void imapParser::parseAcl (parseString & result) -{ - parseOneWordC (result); // skip mailbox name - int outlen = 1; - // The result is user1 perm1 user2 perm2 etc. The caller will sort it out. - while ( outlen && !result.isEmpty() ) { - TQCString word = parseLiteralC (result, false, false, &outlen); - lastResults.append (word); - } -} - -void imapParser::parseAnnotation (parseString & result) -{ - parseOneWordC (result); // skip mailbox name - skipWS (result); - parseOneWordC (result); // skip entry name (we know it since we don't allow wildcards in it) - skipWS (result); - if (result.isEmpty() || result[0] != '(') - return; - result.pos++; - skipWS (result); - int outlen = 1; - // The result is name1 value1 name2 value2 etc. The caller will sort it out. - while ( outlen && !result.isEmpty() && result[0] != ')' ) { - TQCString word = parseLiteralC (result, false, false, &outlen); - lastResults.append (word); - } -} - - -void imapParser::parseQuota (parseString & result) -{ - // quota_response ::= "QUOTA" SP astring SP quota_list - // quota_list ::= "(" #quota_resource ")" - // quota_resource ::= atom SP number SP number - TQCString root = parseOneWordC( result ); - if ( root.isEmpty() ) { - lastResults.append( "" ); - } else { - lastResults.append( root ); - } - if (result.isEmpty() || result[0] != '(') - return; - result.pos++; - skipWS (result); - TQStringList triplet; - int outlen = 1; - while ( outlen && !result.isEmpty() && result[0] != ')' ) { - TQCString word = parseLiteralC (result, false, false, &outlen); - triplet.append(word); - } - lastResults.append( triplet.join(" ") ); -} - -void imapParser::parseQuotaRoot (parseString & result) -{ - // quotaroot_response - // ::= "QUOTAROOT" SP astring *(SP astring) - parseOneWordC (result); // skip mailbox name - skipWS (result); - if ( result.isEmpty() ) - return; - TQStringList roots; - int outlen = 1; - while ( outlen && !result.isEmpty() ) { - TQCString word = parseLiteralC (result, false, false, &outlen); - roots.append (word); - } - lastResults.append( roots.isEmpty()? "" : roots.join(" ") ); -} - -void imapParser::parseCustom (parseString & result) -{ - int outlen = 1; - TQCString word = parseLiteralC (result, false, false, &outlen); - lastResults.append( word ); -} - -void imapParser::parseOtherUser (parseString & result) -{ - lastResults.append( parseOneWordC( result ) ); -} - -void imapParser::parseDelegate (parseString & result) -{ - const TQString email = parseOneWordC( result ); - - TQStringList rights; - int outlen = 1; - while ( outlen && !result.isEmpty() ) { - TQCString word = parseLiteralC( result, false, false, &outlen ); - rights.append( word ); - } - - lastResults.append( email + ":" + rights.join( "," ) ); -} - -void imapParser::parseOutOfOffice (parseString & result) -{ - const TQString state = parseOneWordC (result); - parseOneWordC (result); // skip encoding - - int outlen = 1; - TQCString msg = parseLiteralC (result, false, false, &outlen); - - lastResults.append( state + "^" + TQString::fromUtf8( msg ) ); -} - -void imapParser::parseMyRights (parseString & result) -{ - parseOneWordC (result); // skip mailbox name - Q_ASSERT( lastResults.isEmpty() ); // we can only be called once - lastResults.append (parseOneWordC (result) ); -} - -void imapParser::parseSearch (parseString & result) -{ - ulong value; - - while (parseOneNumber (result, value)) - { - lastResults.append (TQString::number(value)); - } -} - -void imapParser::parsetStatus (parseString & inWords) -{ - lasStatus = imapInfo (); - - parseLiteralC(inWords); // swallow the box - if (inWords.isEmpty() || inWords[0] != '(') - return; - - inWords.pos++; - skipWS (inWords); - - while (!inWords.isEmpty() && inWords[0] != ')') - { - ulong value; - - TQCString label = parseOneWordC(inWords); - if (parseOneNumber (inWords, value)) - { - if (label == "MESSAGES") - lasStatus.setCount (value); - else if (label == "RECENT") - lasStatus.setRecent (value); - else if (label == "UIDVALIDITY") - lasStatus.setUidValidity (value); - else if (label == "UNSEEN") - lasStatus.setUnseen (value); - else if (label == "UIDNEXT") - lasStatus.setUidNext (value); - } - } - - if (inWords[0] == ')') - inWords.pos++; - skipWS (inWords); -} - -void imapParser::parseExists (ulong value, parseString & result) -{ - selectInfo.setCount (value); - result.pos = result.data.size(); -} - -void imapParser::parseExpunge (ulong value, parseString & result) -{ - Q_UNUSED(value); - Q_UNUSED(result); -} - -void imapParser::parseAddressList (parseString & inWords, TQPtrList<mailAddress>& list) -{ - if (inWords.isEmpty()) - return; - if (inWords[0] != '(') - { - parseOneWordC (inWords); // parse NIL - } - else - { - inWords.pos++; - skipWS (inWords); - - while (!inWords.isEmpty () && inWords[0] != ')') - { - if (inWords[0] == '(') { - mailAddress *addr = new mailAddress; - parseAddress(inWords, *addr); - list.append(addr); - } else { - break; - } - } - - if (!inWords.isEmpty() && inWords[0] == ')') - inWords.pos++; - skipWS (inWords); - } -} - -const mailAddress& imapParser::parseAddress (parseString & inWords, mailAddress& retVal) -{ - inWords.pos++; - skipWS (inWords); - - retVal.setFullName(parseLiteralC(inWords)); - retVal.setCommentRaw(parseLiteralC(inWords)); - retVal.setUser(parseLiteralC(inWords)); - retVal.setHost(parseLiteralC(inWords)); - - if (!inWords.isEmpty() && inWords[0] == ')') - inWords.pos++; - skipWS (inWords); - - return retVal; -} - -mailHeader * imapParser::parseEnvelope (parseString & inWords) -{ - mailHeader *envelope = 0; - - if (inWords[0] != '(') - return envelope; - inWords.pos++; - skipWS (inWords); - - envelope = new mailHeader; - - //date - envelope->setDate(parseLiteralC(inWords)); - - //subject - envelope->setSubject(parseLiteralC(inWords)); - - TQPtrList<mailAddress> list; - list.setAutoDelete(true); - - //from - parseAddressList(inWords, list); - if (!list.isEmpty()) { - envelope->setFrom(*list.last()); - list.clear(); - } - - //sender - parseAddressList(inWords, list); - if (!list.isEmpty()) { - envelope->setSender(*list.last()); - list.clear(); - } - - //reply-to - parseAddressList(inWords, list); - if (!list.isEmpty()) { - envelope->setReplyTo(*list.last()); - list.clear(); - } - - //to - parseAddressList (inWords, envelope->to()); - - //cc - parseAddressList (inWords, envelope->cc()); - - //bcc - parseAddressList (inWords, envelope->bcc()); - - //in-reply-to - envelope->setInReplyTo(parseLiteralC(inWords)); - - //message-id - envelope->setMessageId(parseLiteralC(inWords)); - - // see if we have more to come - while (!inWords.isEmpty () && inWords[0] != ')') - { - //eat the extensions to this part - if (inWords[0] == '(') - parseSentence (inWords); - else - parseLiteralC (inWords); - } - - if (!inWords.isEmpty() && inWords[0] == ')') - inWords.pos++; - skipWS (inWords); - - return envelope; -} - -// parse parameter pairs into a dictionary -// caller must clean up the dictionary items -TQAsciiDict < TQString > imapParser::parseDisposition (parseString & inWords) -{ - TQCString disposition; - TQAsciiDict < TQString > retVal (17, false); - - // return value is a shallow copy - retVal.setAutoDelete (false); - - if (inWords[0] != '(') - { - //disposition only - disposition = parseOneWordC (inWords); - } - else - { - inWords.pos++; - skipWS (inWords); - - //disposition - disposition = parseOneWordC (inWords); - retVal = parseParameters (inWords); - if (inWords[0] != ')') - return retVal; - inWords.pos++; - skipWS (inWords); - } - - if (!disposition.isEmpty ()) - { - retVal.insert ("content-disposition", new TQString(disposition)); - } - - return retVal; -} - -// parse parameter pairs into a dictionary -// caller must clean up the dictionary items -TQAsciiDict < TQString > imapParser::parseParameters (parseString & inWords) -{ - TQAsciiDict < TQString > retVal (17, false); - - // return value is a shallow copy - retVal.setAutoDelete (false); - - if (inWords[0] != '(') - { - //better be NIL - parseOneWordC (inWords); - } - else - { - inWords.pos++; - skipWS (inWords); - - while (!inWords.isEmpty () && inWords[0] != ')') - { - TQCString l1 = parseLiteralC(inWords); - TQCString l2 = parseLiteralC(inWords); - retVal.insert (l1, new TQString(l2)); - } - - if (inWords[0] != ')') - return retVal; - inWords.pos++; - skipWS (inWords); - } - - return retVal; -} - -mimeHeader * imapParser::parseSimplePart (parseString & inWords, - TQString & inSection, mimeHeader * localPart) -{ - TQCString subtype; - TQCString typeStr; - TQAsciiDict < TQString > parameters (17, false); - ulong size; - - parameters.setAutoDelete (true); - - if (inWords[0] != '(') - return 0; - - if (!localPart) - localPart = new mimeHeader; - - localPart->setPartSpecifier (inSection); - - inWords.pos++; - skipWS (inWords); - - //body type - typeStr = parseLiteralC(inWords); - - //body subtype - subtype = parseLiteralC(inWords); - - localPart->setType (typeStr + "/" + subtype); - - //body parameter parenthesized list - parameters = parseParameters (inWords); - { - TQAsciiDictIterator < TQString > it (parameters); - - while (it.current ()) - { - localPart->setTypeParm (it.currentKey (), *(it.current ())); - ++it; - } - parameters.clear (); - } - - //body id - localPart->setID (parseLiteralC(inWords)); - - //body description - localPart->setDescription (parseLiteralC(inWords)); - - //body encoding - localPart->setEncoding (parseLiteralC(inWords)); - - //body size - if (parseOneNumber (inWords, size)) - localPart->setLength (size); - - // type specific extensions - if (localPart->getType().upper() == "MESSAGE/RFC822") - { - //envelope structure - mailHeader *envelope = parseEnvelope (inWords); - - //body structure - parseBodyStructure (inWords, inSection, envelope); - - localPart->setNestedMessage (envelope); - - //text lines - ulong lines; - parseOneNumber (inWords, lines); - } - else - { - if (typeStr == "TEXT") - { - //text lines - ulong lines; - parseOneNumber (inWords, lines); - } - - // md5 - parseLiteralC(inWords); - - // body disposition - parameters = parseDisposition (inWords); - { - TQString *disposition = parameters["content-disposition"]; - - if (disposition) - localPart->setDisposition (disposition->ascii ()); - parameters.remove ("content-disposition"); - TQAsciiDictIterator < TQString > it (parameters); - while (it.current ()) - { - localPart->setDispositionParm (it.currentKey (), - *(it.current ())); - ++it; - } - - parameters.clear (); - } - - // body language - parseSentence (inWords); - } - - // see if we have more to come - while (!inWords.isEmpty () && inWords[0] != ')') - { - //eat the extensions to this part - if (inWords[0] == '(') - parseSentence (inWords); - else - parseLiteralC(inWords); - } - if (inWords[0] == ')') - inWords.pos++; - skipWS (inWords); - - return localPart; -} - -mimeHeader * imapParser::parseBodyStructure (parseString & inWords, - TQString & inSection, mimeHeader * localPart) -{ - bool init = false; - if (inSection.isEmpty()) - { - // first run - init = true; - // assume one part - inSection = "1"; - } - int section = 0; - - if (inWords[0] != '(') - { - // skip "" - parseOneWordC (inWords); - return 0; - } - inWords.pos++; - skipWS (inWords); - - if (inWords[0] == '(') - { - TQByteArray subtype; - TQAsciiDict < TQString > parameters (17, false); - TQString outSection; - parameters.setAutoDelete (true); - if (!localPart) - localPart = new mimeHeader; - else - { - // might be filled from an earlier run - localPart->clearNestedParts (); - localPart->clearTypeParameters (); - localPart->clearDispositionParameters (); - // an envelope was passed in so this is the multipart header - outSection = inSection + ".HEADER"; - } - if (inWords[0] == '(' && init) - inSection = "0"; - - // set the section - if ( !outSection.isEmpty() ) { - localPart->setPartSpecifier(outSection); - } else { - localPart->setPartSpecifier(inSection); - } - - // is multipart (otherwise its a simplepart and handled later) - while (inWords[0] == '(') - { - outSection = TQString::number(++section); - if (!init) - outSection = inSection + "." + outSection; - mimeHeader *subpart = parseBodyStructure (inWords, outSection, 0); - localPart->addNestedPart (subpart); - } - - // fetch subtype - subtype = parseOneWordC (inWords); - - localPart->setType ("MULTIPART/" + b2c(subtype)); - - // fetch parameters - parameters = parseParameters (inWords); - { - TQAsciiDictIterator < TQString > it (parameters); - - while (it.current ()) - { - localPart->setTypeParm (it.currentKey (), *(it.current ())); - ++it; - } - parameters.clear (); - } - - // body disposition - parameters = parseDisposition (inWords); - { - TQString *disposition = parameters["content-disposition"]; - - if (disposition) - localPart->setDisposition (disposition->ascii ()); - parameters.remove ("content-disposition"); - TQAsciiDictIterator < TQString > it (parameters); - while (it.current ()) - { - localPart->setDispositionParm (it.currentKey (), - *(it.current ())); - ++it; - } - parameters.clear (); - } - - // body language - parseSentence (inWords); - - } - else - { - // is simple part - inWords.pos--; - inWords.data[inWords.pos] = '('; //fake a sentence - if ( localPart ) - inSection = inSection + ".1"; - localPart = parseSimplePart (inWords, inSection, localPart); - inWords.pos--; - inWords.data[inWords.pos] = ')'; //remove fake - } - - // see if we have more to come - while (!inWords.isEmpty () && inWords[0] != ')') - { - //eat the extensions to this part - if (inWords[0] == '(') - parseSentence (inWords); - else - parseLiteralC(inWords); - } - - if (inWords[0] == ')') - inWords.pos++; - skipWS (inWords); - - return localPart; -} - -void imapParser::parseBody (parseString & inWords) -{ - // see if we got a part specifier - if (inWords[0] == '[') - { - TQCString specifier; - TQCString label; - inWords.pos++; - - specifier = parseOneWordC (inWords, TRUE); - - if (inWords[0] == '(') - { - inWords.pos++; - - while (!inWords.isEmpty () && inWords[0] != ')') - { - label = parseOneWordC (inWords); - } - - if (!inWords.isEmpty () && inWords[0] == ')') - inWords.pos++; - } - if (!inWords.isEmpty () && inWords[0] == ']') - inWords.pos++; - skipWS (inWords); - - // parse the header - if (specifier == "0") - { - mailHeader *envelope = 0; - if (lastHandled) - envelope = lastHandled->getHeader (); - - if (!envelope || seenUid.isEmpty ()) - { - kdDebug(7116) << "imapParser::parseBody - discarding " << envelope << " " << seenUid.ascii () << endl; - // don't know where to put it, throw it away - parseLiteralC(inWords, true); - } - else - { - kdDebug(7116) << "imapParser::parseBody - reading " << envelope << " " << seenUid.ascii () << endl; - // fill it up with data - TQString theHeader = parseLiteralC(inWords, true); - mimeIOTQString myIO; - - myIO.setString (theHeader); - envelope->parseHeader (myIO); - - } - } - else if (specifier == "HEADER.FIELDS") - { - // BODY[HEADER.FIELDS (References)] {n} - //kdDebug(7116) << "imapParser::parseBody - HEADER.FIELDS: " - // << TQCString(label.data(), label.size()+1) << endl; - if (label == "REFERENCES") - { - mailHeader *envelope = 0; - if (lastHandled) - envelope = lastHandled->getHeader (); - - if (!envelope || seenUid.isEmpty ()) - { - kdDebug(7116) << "imapParser::parseBody - discarding " << envelope << " " << seenUid.ascii () << endl; - // don't know where to put it, throw it away - parseLiteralC (inWords, true); - } - else - { - TQCString references = parseLiteralC(inWords, true); - int start = references.find ('<'); - int end = references.findRev ('>'); - if (start < end) - references = references.mid (start, end - start + 1); - envelope->setReferences(references.simplifyWhiteSpace()); - } - } - else - { // not a header we care about throw it away - parseLiteralC(inWords, true); - } - } - else - { - if (specifier.find(".MIME") != -1) - { - mailHeader *envelope = new mailHeader; - TQString theHeader = parseLiteralC(inWords, false); - mimeIOTQString myIO; - myIO.setString (theHeader); - envelope->parseHeader (myIO); - if (lastHandled) - lastHandled->setHeader (envelope); - return; - } - // throw it away - kdDebug(7116) << "imapParser::parseBody - discarding " << seenUid.ascii () << endl; - parseLiteralC(inWords, true); - } - - } - else // no part specifier - { - mailHeader *envelope = 0; - if (lastHandled) - envelope = lastHandled->getHeader (); - - if (!envelope || seenUid.isEmpty ()) - { - kdDebug(7116) << "imapParser::parseBody - discarding " << envelope << " " << seenUid.ascii () << endl; - // don't know where to put it, throw it away - parseSentence (inWords); - } - else - { - kdDebug(7116) << "imapParser::parseBody - reading " << envelope << " " << seenUid.ascii () << endl; - // fill it up with data - TQString section; - mimeHeader *body = parseBodyStructure (inWords, section, envelope); - if (body != envelope) - delete body; - } - } -} - -void imapParser::parseFetch (ulong /* value */, parseString & inWords) -{ - if (inWords[0] != '(') - return; - inWords.pos++; - skipWS (inWords); - - delete lastHandled; - lastHandled = 0; - - while (!inWords.isEmpty () && inWords[0] != ')') - { - if (inWords[0] == '(') - parseSentence (inWords); - else - { - TQCString word = parseLiteralC(inWords, false, true); - - if(!word.isEmpty()) { - switch (word[0]) - { - case 'E': - if (word == "ENVELOPE") - { - mailHeader *envelope = 0; - - if (lastHandled) - envelope = lastHandled->getHeader (); - else - lastHandled = new imapCache(); - - if (envelope && !envelope->getMessageId ().isEmpty ()) - { - // we have seen this one already - // or don't know where to put it - parseSentence (inWords); - } - else - { - envelope = parseEnvelope (inWords); - if (envelope) - { - envelope->setPartSpecifier (seenUid + ".0"); - lastHandled->setHeader (envelope); - lastHandled->setUid (seenUid.toULong ()); - } - } - } - break; - - case 'B': - if (word == "BODY") - { - parseBody (inWords); - } - else if (word == "BODY[]" ) - { - // Do the same as with "RFC822" - parseLiteralC(inWords, true); - } - else if (word == "BODYSTRUCTURE") - { - mailHeader *envelope = 0; - - if (lastHandled) - envelope = lastHandled->getHeader (); - - // fill it up with data - TQString section; - mimeHeader *body = - parseBodyStructure (inWords, section, envelope); - TQByteArray data; - TQDataStream stream( data, IO_WriteOnly ); - if (body) body->serialize(stream); - parseRelay(data); - - delete body; - } - break; - - case 'U': - if (word == "UID") - { - seenUid = parseOneWordC(inWords); - mailHeader *envelope = 0; - if (lastHandled) - envelope = lastHandled->getHeader (); - else - lastHandled = new imapCache(); - - if (seenUid.isEmpty ()) - { - // unknown what to do - kdDebug(7116) << "imapParser::parseFetch - UID empty" << endl; - } - else - { - lastHandled->setUid (seenUid.toULong ()); - } - if (envelope) - envelope->setPartSpecifier (seenUid); - } - break; - - case 'R': - if (word == "RFC822.SIZE") - { - ulong size; - parseOneNumber (inWords, size); - - if (!lastHandled) lastHandled = new imapCache(); - lastHandled->setSize (size); - } - else if (word.find ("RFC822") == 0) - { - // might be RFC822 RFC822.TEXT RFC822.HEADER - parseLiteralC(inWords, true); - } - break; - - case 'I': - if (word == "INTERNALDATE") - { - TQCString date = parseOneWordC(inWords); - if (!lastHandled) lastHandled = new imapCache(); - lastHandled->setDate(date); - } - break; - - case 'F': - if (word == "FLAGS") - { - //kdDebug(7116) << "GOT FLAGS " << inWords.cstr() << endl; - if (!lastHandled) lastHandled = new imapCache(); - lastHandled->setFlags (imapInfo::_flags (inWords.cstr())); - } - break; - - default: - parseLiteralC(inWords); - break; - } - } else { - parseLiteralC(inWords); - } - } - } - - // see if we have more to come - while (!inWords.isEmpty () && inWords[0] != ')') - { - //eat the extensions to this part - if (inWords[0] == '(') - parseSentence (inWords); - else - parseLiteralC(inWords); - } - - if (inWords.isEmpty() || inWords[0] != ')') - return; - inWords.pos++; - skipWS (inWords); -} - - -// default parser -void imapParser::parseSentence (parseString & inWords) -{ - bool first = true; - int stack = 0; - - //find the first nesting parentheses - - while (!inWords.isEmpty () && (stack != 0 || first)) - { - first = false; - skipWS (inWords); - - unsigned char ch = inWords[0]; - switch (ch) - { - case '(': - inWords.pos++; - ++stack; - break; - case ')': - inWords.pos++; - --stack; - break; - case '[': - inWords.pos++; - ++stack; - break; - case ']': - inWords.pos++; - --stack; - break; - default: - parseLiteralC(inWords); - skipWS (inWords); - break; - } - } - skipWS (inWords); -} - -void imapParser::parseRecent (ulong value, parseString & result) -{ - selectInfo.setRecent (value); - result.pos = result.data.size(); -} - -void imapParser::parseNamespace (parseString & result) -{ - if ( result[0] != '(' ) - return; - - TQString delimEmpty; - if ( namespaceToDelimiter.contains( TQString() ) ) - delimEmpty = namespaceToDelimiter[TQString()]; - - namespaceToDelimiter.clear(); - imapNamespaces.clear(); - - // remember what section we're in (user, other users, shared) - int ns = -1; - bool personalAvailable = false; - while ( !result.isEmpty() ) - { - if ( result[0] == '(' ) - { - result.pos++; // tie off ( - if ( result[0] == '(' ) - { - // new namespace section - result.pos++; // tie off ( - ++ns; - } - // namespace prefix - TQCString prefix = parseOneWordC( result ); - // delimiter - TQCString delim = parseOneWordC( result ); - kdDebug(7116) << "imapParser::parseNamespace ns='" << prefix << - "',delim='" << delim << "'" << endl; - if ( ns == 0 ) - { - // at least one personal ns - personalAvailable = true; - } - TQString nsentry = TQString::number( ns ) + "=" + TQString(prefix) + - "=" + TQString(delim); - imapNamespaces.append( nsentry ); - if ( prefix.right( 1 ) == delim ) { - // strip delimiter to get a correct entry for comparisons - prefix.resize( prefix.length() ); - } - namespaceToDelimiter[prefix] = delim; - - result.pos++; // tie off ) - skipWS( result ); - } else if ( result[0] == ')' ) - { - result.pos++; // tie off ) - skipWS( result ); - } else if ( result[0] == 'N' ) - { - // drop NIL - ++ns; - parseOneWordC( result ); - } else { - // drop whatever it is - parseOneWordC( result ); - } - } - if ( !delimEmpty.isEmpty() ) { - // remember default delimiter - namespaceToDelimiter[TQString()] = delimEmpty; - if ( !personalAvailable ) - { - // at least one personal ns would be nice - kdDebug(7116) << "imapParser::parseNamespace - registering own personal ns" << endl; - TQString nsentry = "0==" + delimEmpty; - imapNamespaces.append( nsentry ); - } - } -} - -int imapParser::parseLoop () -{ - parseString result; - - if (!parseReadLine(result.data)) return -1; - - //kdDebug(7116) << result.cstr(); // includes \n - - if (result.data.isEmpty()) - return 0; - if (!sentQueue.count ()) - { - // maybe greeting or BYE everything else SHOULD not happen, use NOOP or IDLE - kdDebug(7116) << "imapParser::parseLoop - unhandledResponse: \n" << result.cstr() << endl; - unhandled << result.cstr(); - } - else - { - imapCommand *current = sentQueue.at (0); - switch (result[0]) - { - case '*': - result.data.resize(result.data.size() - 2); // tie off CRLF - parseUntagged (result); - break; - case '+': - continuation.duplicate(result.data); - break; - default: - { - TQCString tag = parseLiteralC(result); - if (current->id() == tag.data()) - { - result.data.resize(result.data.size() - 2); // tie off CRLF - TQByteArray resultCode = parseLiteral (result); //the result - current->setResult (resultCode); - current->setResultInfo(result.cstr()); - current->setComplete (); - - sentQueue.removeRef (current); - completeQueue.append (current); - if (result.length()) - parseResult (resultCode, result, current->command()); - } - else - { - kdDebug(7116) << "imapParser::parseLoop - unknown tag '" << tag << "'" << endl; - TQCString cstr = tag + " " + result.cstr(); - result.data = cstr; - result.pos = 0; - result.data.resize(cstr.length()); - } - } - break; - } - } - - return 1; -} - -void -imapParser::parseRelay (const TQByteArray & buffer) -{ - Q_UNUSED(buffer); - tqWarning - ("imapParser::parseRelay - virtual function not reimplemented - data lost"); -} - -void -imapParser::parseRelay (ulong len) -{ - Q_UNUSED(len); - tqWarning - ("imapParser::parseRelay - virtual function not reimplemented - announcement lost"); -} - -bool imapParser::parseRead (TQByteArray & buffer, ulong len, ulong relay) -{ - Q_UNUSED(buffer); - Q_UNUSED(len); - Q_UNUSED(relay); - tqWarning - ("imapParser::parseRead - virtual function not reimplemented - no data read"); - return FALSE; -} - -bool imapParser::parseReadLine (TQByteArray & buffer, ulong relay) -{ - Q_UNUSED(buffer); - Q_UNUSED(relay); - tqWarning - ("imapParser::parseReadLine - virtual function not reimplemented - no data read"); - return FALSE; -} - -void -imapParser::parseWriteLine (const TQString & str) -{ - Q_UNUSED(str); - tqWarning - ("imapParser::parseWriteLine - virtual function not reimplemented - no data written"); -} - -void -imapParser::parseURL (const KURL & _url, TQString & _box, TQString & _section, - TQString & _type, TQString & _uid, TQString & _validity, TQString & _info) -{ - TQStringList parameters; - - _box = _url.path (); - kdDebug(7116) << "imapParser::parseURL " << _box << endl; - int paramStart = _box.find("/;"); - if ( paramStart > -1 ) - { - TQString paramString = _box.right( _box.length() - paramStart-2 ); - parameters = TQStringList::split (';', paramString); //split parameters - _box.truncate( paramStart ); // strip parameters - } - // extract parameters - for (TQStringList::ConstIterator it (parameters.begin ()); - it != parameters.end (); ++it) - { - TQString temp = (*it); - - int pt = temp.find ('/'); - if (pt > 0) - { - if (temp.findRev ('"', pt) == -1 || temp.find('"', pt) == -1) - { - // if we have non-quoted '/' separator we'll just nuke it - temp.truncate(pt); - } - } - if (temp.find ("section=", 0, false) == 0) - _section = temp.right (temp.length () - 8); - else if (temp.find ("type=", 0, false) == 0) - _type = temp.right (temp.length () - 5); - else if (temp.find ("uid=", 0, false) == 0) - _uid = temp.right (temp.length () - 4); - else if (temp.find ("uidvalidity=", 0, false) == 0) - _validity = temp.right (temp.length () - 12); - else if (temp.find ("info=", 0, false) == 0) - _info = temp.right (temp.length () - 5); - } -// kdDebug(7116) << "URL: section= " << _section << ", type= " << _type << ", uid= " << _uid << endl; -// kdDebug(7116) << "URL: user() " << _url.user() << endl; -// kdDebug(7116) << "URL: path() " << _url.path() << endl; -// kdDebug(7116) << "URL: encodedPathAndQuery() " << _url.encodedPathAndQuery() << endl; - - if (!_box.isEmpty ()) - { - // strip / - if (_box[0] == '/') - _box = _box.right (_box.length () - 1); - if (!_box.isEmpty () && _box[_box.length () - 1] == '/') - _box.truncate(_box.length() - 1); - } - kdDebug(7116) << "URL: box= " << _box << ", section= " << _section << ", type= " - << _type << ", uid= " << _uid << ", validity= " << _validity << ", info= " << _info << endl; -} - - -TQCString imapParser::parseLiteralC(parseString & inWords, bool relay, bool stopAtBracket, int *outlen) { - - if (!inWords.isEmpty() && inWords[0] == '{') - { - TQCString retVal; - long srunLen = inWords.find ('}', 1); // Can return -1, so use a signed long - if (srunLen > 0) - { - ulong runLen = (ulong)srunLen; - bool proper; - ulong runLenSave = runLen + 1; - TQCString tmpstr(runLen); - inWords.takeMidNoResize(tmpstr, 1, runLen - 1); - runLen = tmpstr.toULong (&proper); - inWords.pos += runLenSave; - if (proper) - { - //now get the literal from the server - if (relay) - parseRelay (runLen); - TQByteArray rv; - parseRead (rv, runLen, relay ? runLen : 0); - rv.resize(TQMAX(runLen, rv.size())); // what's the point? - retVal = b2c(rv); - inWords.clear(); - parseReadLine (inWords.data); // must get more - - // no duplicate data transfers - relay = false; - } - else - { - kdDebug(7116) << "imapParser::parseLiteral - error parsing {} - " /*<< strLen*/ << endl; - } - } - else - { - inWords.clear(); - kdDebug(7116) << "imapParser::parseLiteral - error parsing unmatched {" << endl; - } - if (outlen) { - *outlen = retVal.length(); // optimize me - } - skipWS (inWords); - return retVal; - } - - return parseOneWordC(inWords, stopAtBracket, outlen); -} - -// does not know about literals ( {7} literal ) -TQCString imapParser::parseOneWordC (parseString & inWords, bool stopAtBracket, int *outLen) -{ - uint retValSize = 0; - uint len = inWords.length(); - if (len == 0) { - return TQCString(); - } - - if (len > 0 && inWords[0] == '"') - { - unsigned int i = 1; - bool quote = FALSE; - while (i < len && (inWords[i] != '"' || quote)) - { - if (inWords[i] == '\\') quote = !quote; - else quote = FALSE; - i++; - } - if (i < len) - { - TQCString retVal(i); - inWords.pos++; - inWords.takeLeftNoResize(retVal, i - 1); - len = i - 1; - int offset = 0; - for (unsigned int j = 0; j <= len; j++) { - if (retVal[j] == '\\') { - offset++; - j++; - } - retVal[j - offset] = retVal[j]; - } - retVal[len - offset] = 0; - retValSize = len - offset; - inWords.pos += i; - skipWS (inWords); - if (outLen) { - *outLen = retValSize; - } - return retVal; - } - else - { - kdDebug(7116) << "imapParser::parseOneWord - error parsing unmatched \"" << endl; - TQCString retVal = inWords.cstr(); - retValSize = len; - inWords.clear(); - if (outLen) { - *outLen = retValSize; - } - return retVal; - } - } - else - { - // not quoted - unsigned int i; - // search for end - for (i = 0; i < len; ++i) { - char ch = inWords[i]; - if (ch <= ' ' || ch == '(' || ch == ')' || - (stopAtBracket && (ch == '[' || ch == ']'))) - break; - } - - TQCString retVal(i+1); - inWords.takeLeftNoResize(retVal, i); - retValSize = i; - inWords.pos += i; - - if (retVal == "NIL") { - retVal.truncate(0); - retValSize = 0; - } - skipWS (inWords); - if (outLen) { - *outLen = retValSize; - } - return retVal; - } -} - -bool imapParser::parseOneNumber (parseString & inWords, ulong & num) -{ - bool valid; - num = parseOneWordC(inWords, TRUE).toULong(&valid); - return valid; -} - -bool imapParser::hasCapability (const TQString & cap) -{ - TQString c = cap.lower(); -// kdDebug(7116) << "imapParser::hasCapability - Looking for '" << cap << "'" << endl; - for (TQStringList::ConstIterator it = imapCapabilities.begin (); - it != imapCapabilities.end (); ++it) - { -// kdDebug(7116) << "imapParser::hasCapability - Examining '" << (*it) << "'" << endl; - if ( !(kasciistricmp(c.ascii(), (*it).ascii())) ) - { - return true; - } - } - return false; -} - -void imapParser::removeCapability (const TQString & cap) -{ - imapCapabilities.remove(cap.lower()); -} - -TQString imapParser::namespaceForBox( const TQString & box ) -{ - kdDebug(7116) << "imapParse::namespaceForBox " << box << endl; - TQString myNamespace; - if ( !box.isEmpty() ) - { - TQValueList<TQString> list = namespaceToDelimiter.keys(); - TQString cleanPrefix; - for ( TQValueList<TQString>::Iterator it = list.begin(); it != list.end(); ++it ) - { - if ( !(*it).isEmpty() && box.find( *it ) != -1 ) - return (*it); - } - } - return myNamespace; -} - |