kde-playground/kdepimlibs/kimap/listjob.cpp
2015-04-14 21:49:29 +00:00

222 lines
6.2 KiB
C++

/*
Copyright (c) 2009 Kevin Ottens <ervin@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "listjob.h"
#include <boost/bind.hpp>
#include <QtCore/QTimer>
#include <KDE/KLocalizedString>
#include "job_p.h"
#include "message_p.h"
#include "rfccodecs.h"
#include "session_p.h"
namespace KIMAP
{
class ListJobPrivate : public JobPrivate
{
public:
ListJobPrivate( ListJob *job, Session *session, const QString& name ) : JobPrivate( session, name ), q( job ), option( ListJob::NoOption ) { }
~ListJobPrivate() { }
void emitPendings()
{
if ( pendingDescriptors.isEmpty() ) {
return;
}
emit q->mailBoxesReceived( pendingDescriptors, pendingFlags );
pendingDescriptors.clear();
pendingFlags.clear();
}
ListJob * const q;
ListJob::Option option;
QList<MailBoxDescriptor> namespaces;
QByteArray command;
QTimer emitPendingsTimer;
QList<MailBoxDescriptor> pendingDescriptors;
QList< QList<QByteArray> > pendingFlags;
};
}
using namespace KIMAP;
ListJob::ListJob( Session *session )
: Job( *new ListJobPrivate( this, session, i18n( "List" ) ) )
{
Q_D( ListJob );
connect( &d->emitPendingsTimer, SIGNAL(timeout()),
this, SLOT(emitPendings()) );
}
ListJob::~ListJob()
{
}
void ListJob::setIncludeUnsubscribed( bool include )
{
Q_D( ListJob );
if ( include ) {
d->option = ListJob::IncludeUnsubscribed;
} else {
d->option = ListJob::NoOption;
}
}
bool ListJob::isIncludeUnsubscribed() const
{
Q_D( const ListJob );
return ( d->option == ListJob::IncludeUnsubscribed );
}
void ListJob::setOption( Option option )
{
Q_D( ListJob );
d->option = option;
}
ListJob::Option ListJob::option() const
{
Q_D( const ListJob );
return d->option;
}
void ListJob::setQueriedNamespaces( const QList<MailBoxDescriptor> &namespaces )
{
Q_D( ListJob );
d->namespaces = namespaces;
}
QList<MailBoxDescriptor> ListJob::queriedNamespaces() const
{
Q_D( const ListJob );
return d->namespaces;
}
QList<MailBoxDescriptor> ListJob::mailBoxes() const
{
return QList<MailBoxDescriptor>();
}
QMap< MailBoxDescriptor, QList<QByteArray> > ListJob::flags() const
{
return QMap< MailBoxDescriptor, QList<QByteArray> >();
}
void ListJob::doStart()
{
Q_D( ListJob );
switch ( d->option ) {
break;
case IncludeUnsubscribed:
d->command = "LIST";
break;
case IncludeFolderRoleFlags:
d->command = "XLIST";
break;
case NoOption:
default:
d->command = "LSUB";
}
d->emitPendingsTimer.start( 100 );
if ( d->namespaces.isEmpty() ) {
d->tags << d->sessionInternal()->sendCommand( d->command, "\"\" *" );
} else {
foreach ( const MailBoxDescriptor &descriptor, d->namespaces ) {
QString parameters = QLatin1String("\"\" \"%1\"");
if ( descriptor.name.endsWith( descriptor.separator ) ) {
QString name = encodeImapFolderName( descriptor.name );
name.chop( 1 );
d->tags << d->sessionInternal()->sendCommand( d->command,
parameters.arg( name ).toUtf8() );
}
d->tags << d->sessionInternal()->sendCommand( d->command,
parameters.arg( descriptor.name + QLatin1Char('*') ).toUtf8() );
}
}
}
void ListJob::handleResponse( const Message &response )
{
Q_D( ListJob );
// We can predict it'll be handled by handleErrorReplies() so stop
// the timer now so that result() will really be the last emitted signal.
if ( !response.content.isEmpty() &&
d->tags.size() == 1 &&
d->tags.contains( response.content.first().toString() ) ) {
d->emitPendingsTimer.stop();
d->emitPendings();
}
if ( handleErrorReplies( response ) == NotHandled ) {
if ( response.content.size() >= 5 && response.content[1].toString() == d->command ) {
QList<QByteArray> flags = response.content[2].toList();
std::transform( flags.begin(), flags.end(), flags.begin(), boost::bind( &QByteArray::toLower, _1 ) );
QByteArray separator = response.content[3].toString();
if ( separator.isEmpty() ) {
// Defaults to / for servers reporting an empty list
// it's supposedly not a problem as servers doing that
// only do it for mailboxes with no child.
separator = "/"; //krazy:exclude=doublequote_chars since a QByteArray
}
Q_ASSERT( separator.size() == 1 );
QByteArray fullName;
for ( int i=4; i<response.content.size(); i++ ) {
fullName += response.content[i].toString() + ' ';
}
fullName.chop( 1 );
fullName = decodeImapFolderName( fullName );
MailBoxDescriptor mailBoxDescriptor;
mailBoxDescriptor.separator = QLatin1Char( separator[0] );
mailBoxDescriptor.name = QString::fromUtf8( fullName );
convertInboxName( mailBoxDescriptor );
d->pendingDescriptors << mailBoxDescriptor;
d->pendingFlags << flags;
}
}
}
void ListJob::convertInboxName(KIMAP::MailBoxDescriptor& descriptor)
{
//Inbox must be case sensitive, according to the RFC, so make it always uppercase
QStringList pathParts = descriptor.name.split( descriptor.separator );
if ( !pathParts.isEmpty() &&
pathParts[0].compare( QLatin1String( "INBOX" ), Qt::CaseInsensitive ) == 0 ) {
pathParts.removeAt( 0 );
descriptor.name = QLatin1String( "INBOX" );
if ( !pathParts.isEmpty() ) {
descriptor.name += descriptor.separator + pathParts.join( descriptor.separator );
}
}
}
#include "moc_listjob.cpp"