• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KIMAP Library

session.cpp

00001 /*
00002     Copyright (c) 2009 Kevin Ottens <ervin@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "session.h"
00021 #include "session_p.h"
00022 #include "sessionuiproxy.h"
00023 
00024 #include <QtCore/QDebug>
00025 #include <QtCore/QTimer>
00026 
00027 #include <KDE/KMessageBox>
00028 #include <KDE/KLocale>
00029 
00030 #include "job.h"
00031 #include "message_p.h"
00032 #include "sessionthread_p.h"
00033 #include "rfccodecs.h"
00034 
00035 Q_DECLARE_METATYPE(KTcpSocket::SslVersion)
00036 Q_DECLARE_METATYPE(QSslSocket::SslMode)
00037 static const int _kimap_sslVersionId = qRegisterMetaType<KTcpSocket::SslVersion>();
00038 
00039 using namespace KIMAP;
00040 
00041 Session::Session( const QString &hostName, quint16 port, QObject *parent)
00042   : QObject(parent), d(new SessionPrivate(this))
00043 {
00044   d->isSocketConnected = false;
00045   d->state = Disconnected;
00046   d->jobRunning = false;
00047 
00048   d->thread = new SessionThread(hostName, port, this);
00049   connect(d->thread, SIGNAL(encryptionNegotiationResult(bool)), d, SIGNAL(encryptionNegotiationResult(bool)));
00050   connect(d->thread, SIGNAL(sslError(const KSslErrorUiData&)), this, SLOT(handleSslError(const KSslErrorUiData&)));
00051 
00052   d->thread->start();
00053 }
00054 
00055 Session::~Session()
00056 {
00057   delete d->thread;
00058 }
00059 
00060 void Session::setUiProxy(SessionUiProxy *proxy)
00061 {
00062   d->uiProxy = proxy;
00063 }
00064 
00065 QString Session::hostName() const
00066 {
00067   return d->thread->hostName();
00068 }
00069 
00070 quint16 Session::port() const
00071 {
00072   return d->thread->port();
00073 }
00074 
00075 Session::State Session::state() const
00076 {
00077   return d->state;
00078 }
00079 
00080 QByteArray Session::serverGreeting() const
00081 {
00082   return d->greeting;
00083 }
00084 
00085 void SessionPrivate::handleSslError(const KSslErrorUiData& errorData)
00086 {
00087   if (uiProxy && uiProxy->ignoreSslError(errorData)) {
00088     QMetaObject::invokeMethod( thread, "sslErrorHandlerResponse", Q_ARG(bool, true) );
00089   } else {
00090     QMetaObject::invokeMethod( thread, "sslErrorHandlerResponse", Q_ARG(bool, false) );
00091   }
00092 }
00093 
00094 SessionPrivate::SessionPrivate( Session *session )
00095   : q(session),
00096     state(Session::Disconnected),
00097     uiProxy(0),
00098     currentJob(0),
00099     tagCount(0)
00100 {
00101 }
00102 
00103 void SessionPrivate::addJob(Job *job)
00104 {
00105   queue.append(job);
00106 
00107   QObject::connect( job, SIGNAL(result(KJob*)), q, SLOT(jobDone(KJob*)) );
00108   QObject::connect( job, SIGNAL(destroyed(QObject*)), q, SLOT(jobDestroyed(QObject*)) );
00109 
00110   startNext();
00111 }
00112 
00113 void SessionPrivate::startNext()
00114 {
00115   QTimer::singleShot( 0, q, SLOT(doStartNext()) );
00116 }
00117 
00118 void SessionPrivate::doStartNext()
00119 {
00120   if ( queue.isEmpty() || jobRunning || !isSocketConnected ) {
00121     return;
00122   }
00123 
00124   jobRunning = true;
00125 
00126   currentJob = queue.dequeue();
00127   currentJob->doStart();
00128 }
00129 
00130 void SessionPrivate::jobDone( KJob *job )
00131 {
00132   Q_ASSERT( job == currentJob );
00133 
00134   jobRunning = false;
00135   currentJob = 0;
00136   startNext();
00137 }
00138 
00139 void SessionPrivate::jobDestroyed( QObject *job )
00140 {
00141   queue.removeAll( static_cast<KIMAP::Job*>( job ) );
00142   if ( currentJob == job )
00143     currentJob = 0;
00144 }
00145 
00146 void SessionPrivate::responseReceived( const Message &response )
00147 {
00148   QByteArray tag;
00149   QByteArray code;
00150 
00151   if ( response.content.size()>=1 ) {
00152     tag = response.content[0].toString();
00153   }
00154 
00155   if ( response.content.size()>=2 ) {
00156     code = response.content[1].toString();
00157   }
00158 
00159   switch ( state ) {
00160   case Session::Disconnected:
00161     if ( code=="OK" ) {
00162       state = Session::NotAuthenticated;
00163 
00164       Message simplified = response;
00165       simplified.content.removeFirst(); // Strip the tag
00166       simplified.content.removeFirst(); // Strip the code
00167       greeting = simplified.toString().trimmed(); // Save the server greeting
00168 
00169       startNext();
00170     } else if ( code=="PREAUTH" ) {
00171       state = Session::Authenticated;
00172 
00173       Message simplified = response;
00174       simplified.content.removeFirst(); // Strip the tag
00175       simplified.content.removeFirst(); // Strip the code
00176       greeting = simplified.toString().trimmed(); // Save the server greeting
00177 
00178       startNext();
00179     } else {
00180       thread->closeSocket();
00181       QTimer::singleShot( 1000, thread, SLOT( reconnect() ) );
00182     }
00183     return;
00184   case Session::NotAuthenticated:
00185     if ( code=="OK" && tag==authTag ) {
00186       state = Session::Authenticated;
00187     }
00188     break;
00189   case Session::Authenticated:
00190     if ( code=="OK" && tag==selectTag ) {
00191       state = Session::Selected;
00192       currentMailBox = upcomingMailBox;
00193     }
00194     break;
00195   case Session::Selected:
00196     if ( ( code=="OK" && tag==closeTag )
00197       || ( code!="OK" && tag==selectTag) ) {
00198       state = Session::Authenticated;
00199       currentMailBox = QByteArray();
00200     } else if ( code=="OK" && tag==selectTag ) {
00201       currentMailBox = upcomingMailBox;
00202     }
00203     break;
00204   }
00205 
00206   if (tag==authTag) authTag.clear();
00207   if (tag==selectTag) selectTag.clear();
00208   if (tag==closeTag) closeTag.clear();
00209 
00210   // If a job is running forward it the response
00211   if ( currentJob!=0 ) {
00212     currentJob->handleResponse( response );
00213   } else {
00214     qWarning() << "A message was received from the server with no job to handle it";
00215   }
00216 }
00217 
00218 QByteArray SessionPrivate::sendCommand( const QByteArray &command, const QByteArray &args )
00219 {
00220   QByteArray tag = 'A' + QByteArray::number(++tagCount).rightJustified(6, '0');
00221 
00222   QByteArray payload = tag+' '+command;
00223   if ( !args.isEmpty() ) {
00224     payload+= ' '+args;
00225   }
00226   payload+="\r\n";
00227 
00228   thread->sendData(payload);
00229 
00230   if ( command=="LOGIN" || command=="AUTHENTICATE" ) {
00231     authTag = tag;
00232   } else if ( command=="SELECT" || command=="EXAMINE" ) {
00233     selectTag = tag;
00234     upcomingMailBox = args;
00235     upcomingMailBox.remove( 0, 1 );
00236     upcomingMailBox.chop( 1 );
00237     upcomingMailBox = KIMAP::decodeImapFolderName( upcomingMailBox );
00238   } else if ( command=="CLOSE" ) {
00239     closeTag = tag;
00240   }
00241 
00242   return tag;
00243 }
00244 
00245 void SessionPrivate::sendData( const QByteArray &data )
00246 {
00247   thread->sendData(data+"\r\n");
00248 }
00249 
00250 void SessionPrivate::socketConnected()
00251 {
00252   isSocketConnected = true;
00253   startNext();
00254 }
00255 
00256 void SessionPrivate::socketDisconnected()
00257 {
00258   isSocketConnected = false;
00259   state = Session::Disconnected;
00260   thread->closeSocket();
00261 
00262   if ( currentJob ) {
00263     currentJob->connectionLost();
00264   }
00265 }
00266 
00267 void SessionPrivate::socketError()
00268 {
00269   //qWarning() << "Socket error occurred:" << socket->errorString();
00270   socketDisconnected();
00271 }
00272 
00273 void SessionPrivate::startSsl(const KTcpSocket::SslVersion &version)
00274 {
00275   QMetaObject::invokeMethod( thread, "startSsl", Qt::QueuedConnection, Q_ARG(KTcpSocket::SslVersion, version) );
00276 }
00277 
00278 QString SessionPrivate::selectedMailBox() const
00279 {
00280   return QString::fromUtf8( currentMailBox );
00281 }
00282 
00283 #include "session.moc"
00284 #include "session_p.moc"

KIMAP Library

Skip menu "KIMAP Library"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.2-20100208
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal