kioslaves

imapparser.h

Go to the documentation of this file.
00001 #ifndef _IMAPPARSER_H
00002 #define _IMAPPARSER_H
00003 /**********************************************************************
00004  *
00005  *   imapparser.h  - IMAP4rev1 Parser
00006  *   Copyright (C) 2001-2002 Michael Haeckel <haeckel@kde.org>
00007  *   Copyright (C) 2000 s.carstens@gmx.de
00008  *
00009  *   This program is free software; you can redistribute it and/or modify
00010  *   it under the terms of the GNU General Public License as published by
00011  *   the Free Software Foundation; either version 2 of the License, or
00012  *   (at your option) any later version.
00013  *
00014  *   This program is distributed in the hope that it will be useful,
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *   GNU General Public License for more details.
00018  *
00019  *   You should have received a copy of the GNU General Public License
00020  *   along with this program; if not, write to the Free Software
00021  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  *   Send comments and bug fixes to s.carstens@gmx.de
00024  *
00025  *********************************************************************/
00026 
00027 #include <qstringlist.h>
00028 #include <qvaluelist.h>
00029 #include <qptrlist.h>
00030 #include <qasciidict.h>
00031 
00032 #include <kio/authinfo.h>
00033 #include <kio/slavebase.h>
00034 
00035 #include "imaplist.h"
00036 #include "imapcommand.h"
00037 #include "imapinfo.h"
00038 
00039 #include "mailheader.h"
00040 
00041 class KURL;
00042 class QString;
00043 class mailAddress;
00044 class mimeHeader;
00045 
00046 
00052 class parseString
00053 {
00054 public:
00055   parseString() { pos = 0; }
00056   char operator[](uint i) const { return data[i + pos]; }
00057   bool isEmpty() const { return pos >= data.size(); }
00058   QCString cstr() const
00059   {
00060     if (pos >= data.size()) return QCString();
00061     return QCString(data.data() + pos, data.size() - pos + 1);
00062   }
00063   int find(char c, int index = 0)
00064   {
00065     int res = data.find(c, index + pos);
00066     return (res == -1) ? res : (res - pos);
00067   }
00068   // Warning: does not check for going past end of "data"
00069   void takeLeft(QCString& dest, uint len) const
00070   {
00071     dest.resize(len + 1);
00072     qmemmove(dest.data(), data.data() + pos, len);
00073   }
00074   // Warning: does not check for going past end of "data"
00075   void takeLeftNoResize(QCString& dest, uint len) const
00076   {
00077     qmemmove(dest.data(), data.data() + pos, len);
00078   }
00079   // Warning: does not check for going past end of "data"
00080   void takeMid(QCString& dest, uint start, uint len) const
00081   {
00082     dest.resize(len + 1);
00083     qmemmove(dest.data(), data.data() + pos + start, len);
00084   }
00085   // Warning: does not check for going past end of "data"
00086   void takeMidNoResize(QCString& dest, uint start, uint len) const
00087   {
00088     qmemmove(dest.data(), data.data() + pos + start, len);
00089   }
00090   void clear()
00091   {
00092     data.resize(0);
00093     pos = 0;
00094   }
00095   uint length()
00096   {
00097     return data.size() - pos;
00098   }
00099   void fromString(const QString &s)
00100   {
00101     clear();
00102     data.duplicate(s.latin1(), s.length());
00103   }
00104   QByteArray data;
00105   uint pos;
00106 };
00107 
00108 class imapCache
00109 {
00110 public:
00111   imapCache ()
00112   {
00113     myHeader = NULL;
00114     mySize = 0;
00115     myFlags = 0;
00116     myUid = 0;
00117   }
00118 
00119   ~imapCache ()
00120   {
00121     if (myHeader) delete myHeader;
00122   }
00123 
00124   mailHeader *getHeader ()
00125   {
00126     return myHeader;
00127   }
00128   void setHeader (mailHeader * inHeader)
00129   {
00130     myHeader = inHeader;
00131   }
00132 
00133   ulong getSize ()
00134   {
00135     return mySize;
00136   }
00137   void setSize (ulong inSize)
00138   {
00139     mySize = inSize;
00140   }
00141 
00142   ulong getUid ()
00143   {
00144     return myUid;
00145   }
00146   void setUid (ulong inUid)
00147   {
00148     myUid = inUid;
00149   }
00150 
00151   ulong getFlags ()
00152   {
00153     return myFlags;
00154   }
00155   void setFlags (ulong inFlags)
00156   {
00157     myFlags = inFlags;
00158   }
00159 
00160   QCString getDate ()
00161   {
00162     return myDate;
00163   }
00164   void setDate (const QCString & _str)
00165   {
00166     myDate = _str;
00167   }
00168   void clear()
00169   {
00170     if (myHeader) delete myHeader;
00171     myHeader = NULL;
00172     mySize = 0;
00173     myFlags = 0;
00174     myDate = QCString();
00175     myUid = 0;
00176   }
00177 
00178 protected:
00179   mailHeader * myHeader;
00180   ulong mySize;
00181   ulong myFlags;
00182   ulong myUid;
00183   QCString myDate;
00184 };
00185 
00186 
00187 class imapParser
00188 {
00189 
00190 public:
00191 
00193   enum IMAP_STATE
00194   {
00195     ISTATE_NO,       
00196     ISTATE_CONNECT,  
00197     ISTATE_LOGIN,    
00198     ISTATE_SELECT    
00199   };
00200 
00201 public:
00202     imapParser ();
00203     virtual ~ imapParser ();
00204 
00206   enum IMAP_STATE getState () { return currentState; }
00208   void setState(enum IMAP_STATE state) { currentState = state; }
00209 
00210   /* @brief return the currently selected mailbox */
00211   const QString getCurrentBox ()
00212   {
00213     return rfcDecoder::fromIMAP(currentBox);
00214   };
00215 
00221   imapCommand *sendCommand (imapCommand * aCmd);
00227   imapCommand *doCommand (imapCommand * aCmd);
00228 
00229 
00237   bool clientLogin (const QString & aUser, const QString & aPass, QString & resultInfo);
00247   bool clientAuthenticate (KIO::SlaveBase *slave, KIO::AuthInfo &ai, const QString & aFQDN,
00248     const QString & aAuth, bool isSSL, QString & resultInfo);
00249 
00254   int parseLoop ();
00255 
00260   void parseUntagged (parseString & result);
00261 
00263   void parseRecent (ulong value, parseString & result);
00265   void parseResult (QByteArray & result, parseString & rest,
00266                     const QString & command = QString::null);
00268   void parseCapability (parseString & result);
00270   void parseFlags (parseString & result);
00272   void parseList (parseString & result);
00274   void parseLsub (parseString & result);
00276   void parseListRights (parseString & result);
00278   void parseMyRights (parseString & result);
00280   void parseSearch (parseString & result);
00282   void parseStatus (parseString & result);
00284   void parseExists (ulong value, parseString & result);
00286   void parseExpunge (ulong value, parseString & result);
00288   void parseAcl (parseString & result);
00290   void parseAnnotation (parseString & result);
00292   void parseNamespace (parseString & result);
00294   void parseQuotaRoot (parseString & result);
00296   void parseQuota (parseString & result);
00298   void parseCustom (parseString & result);
00300   void parseOtherUser (parseString & result);
00302   void parseDelegate (parseString & result);
00304   void parseOutOfOffice (parseString & result);
00305 
00310   void parseFetch (ulong value, parseString & inWords);
00311 
00313   mailHeader *parseEnvelope (parseString & inWords);
00315   void parseAddressList (parseString & inWords, QPtrList<mailAddress>& list);
00317   const mailAddress& parseAddress (parseString & inWords, mailAddress& buffer);
00318 
00320   void parseBody (parseString & inWords);
00321 
00323   mimeHeader *parseBodyStructure (parseString & inWords,
00324     QString & section, mimeHeader * inHeader = 0);
00325 
00327   mimeHeader *parseSimplePart (parseString & inWords, QString & section,
00328       mimeHeader * localPart = 0);
00329 
00331   QAsciiDict < QString > parseParameters (parseString & inWords);
00332 
00337   QAsciiDict < QString > parseDisposition (parseString & inWords);
00338 
00339   // reimplement these
00340 
00342   virtual void parseRelay (const QByteArray & buffer);
00343 
00346   virtual void parseRelay (ulong);
00347 
00349   virtual bool parseRead (QByteArray & buffer, ulong len, ulong relay = 0);
00350 
00352   virtual bool parseReadLine (QByteArray & buffer, ulong relay = 0);
00353 
00355   virtual void parseWriteLine (const QString &);
00356 
00357   // generic parser routines
00358 
00360   void parseSentence (parseString & inWords);
00361 
00363   QCString parseLiteralC(parseString & inWords, bool relay = false,
00364                            bool stopAtBracket = false, int *outlen = 0);
00365   inline QByteArray parseLiteral (parseString & inWords, bool relay = false,
00366                            bool stopAtBracket = false) {
00367     int len = 0; // string size
00368     // Choice: we can create an extra QCString, or we can get the buffer in
00369     // the wrong size to start.  Let's try option b.
00370     QCString tmp = parseLiteralC(inWords, relay, stopAtBracket, &len);
00371     return QByteArray().duplicate(tmp.data(), len);
00372   }
00373 
00374   // static parser routines, can be used elsewhere
00375 
00376   static QCString b2c(const QByteArray &ba)
00377   { return QCString(ba.data(), ba.size() + 1); }
00378 
00380   static QCString parseOneWordC (parseString & inWords,
00381     bool stopAtBracket = FALSE, int *len = 0);
00382 
00384   static bool parseOneNumber (parseString & inWords, ulong & num);
00385 
00387   static void parseURL (const KURL & _url, QString & _box, QString & _section,
00388                         QString & _type, QString & _uid, QString & _validity,
00389                         QString & _info);
00390 
00391 
00395   imapCache *getLastHandled ()
00396   {
00397     return lastHandled;
00398   };
00399 
00401   const QStringList & getResults ()
00402   {
00403     return lastResults;
00404   };
00405 
00407   const imapInfo & getStatus ()
00408   {
00409     return lastStatus;
00410   };
00412   const imapInfo & getSelected ()
00413   {
00414     return selectInfo;
00415   };
00416 
00417   const QByteArray & getContinuation ()
00418   {
00419     return continuation;
00420   };
00421 
00423   bool hasCapability (const QString &);
00424 
00425   void removeCapability (const QString & cap);
00426 
00427   static inline void skipWS (parseString & inWords)
00428   {
00429     char c;
00430     while (!inWords.isEmpty() &&
00431       ((c = inWords[0]) == ' ' || c == '\t' || c == '\r' || c == '\n'))
00432     {
00433       inWords.pos++;
00434     }
00435   }
00436 
00438   QString namespaceForBox( const QString & box );
00439 
00440 
00441 protected:
00442 
00444   enum IMAP_STATE currentState;
00445 
00447   QString currentBox;
00448 
00450   imapInfo selectInfo;
00451 
00453   imapInfo lastStatus;
00454 
00456   QStringList imapCapabilities;
00457 
00459   QValueList < imapList > listResponses;
00460 
00462   QPtrList < imapCommand > sentQueue;  // no autodelete
00463   QPtrList < imapCommand > completeQueue;  // autodelete !!
00464 
00468   QStringList unhandled;
00469 
00471   QByteArray continuation;
00472 
00474   QString seenUid;
00475   imapCache *lastHandled;
00476 
00477   ulong commandCounter;
00478 
00480   QStringList lastResults;
00481 
00486   QMap<QString, QString> namespaceToDelimiter;
00487 
00492   QStringList imapNamespaces;
00493 
00494 private:
00495 
00497   imapParser & operator = (const imapParser &); // hide the copy ctor
00498 
00499 };
00500 #endif