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

228 lines
5 KiB
C++

/*
Copyright (C) 2006-2007 KovoKs <info@kovoks.nl>
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.
*/
// Uncomment the next line for full comm debug
// #define comm_debug
// Own
#include "socket.h"
// Qt
#include <QByteArray>
#include <QSslSocket>
// KDE
#include <KDebug>
#include <ksocketfactory.h>
using namespace MailTransport;
namespace MailTransport {
class SocketPrivate
{
public:
SocketPrivate( Socket *s );
Socket *const q;
QSslSocket *socket;
QString server;
QString protocol;
int port;
bool secure;
// slots
void slotConnected();
void slotStateChanged( QAbstractSocket::SocketState state );
void slotModeChanged( QSslSocket::SslMode state );
void slotSocketRead();
void slotSslErrors( const QList<QSslError> &errors );
private:
QString m_msg;
};
}
SocketPrivate::SocketPrivate( Socket *s ) : q( s )
{
}
void SocketPrivate::slotConnected()
{
kDebug();
if ( !secure ) {
kDebug() << "normal connect";
emit q->connected();
} else {
kDebug() << "encrypted connect";
socket->startClientEncryption();
}
}
void SocketPrivate::slotStateChanged( QAbstractSocket::SocketState state )
{
#ifdef comm_debug
kDebug() << "State is now:" << ( int ) state;
#endif
if ( state == QAbstractSocket::UnconnectedState ) {
emit q->failed();
}
}
void SocketPrivate::slotModeChanged( QSslSocket::SslMode state )
{
#ifdef comm_debug
kDebug() << "Mode is now:" << state;
#endif
if ( state == QSslSocket::SslClientMode ) {
emit q->tlsDone();
}
}
void SocketPrivate::slotSocketRead()
{
kDebug();
if ( !socket ) {
return;
}
m_msg += QLatin1String( socket->readAll() );
if ( !m_msg.endsWith( QLatin1Char( '\n' ) ) ) {
return;
}
#ifdef comm_debug
kDebug() << socket->isEncrypted() << m_msg.trimmed();
#endif
emit q->data( m_msg );
m_msg.clear();
}
void SocketPrivate::slotSslErrors( const QList<QSslError> & )
{
kDebug();
/* We can safely ignore the errors, we are only interested in the
capabilities. We're not sending auth info. */
socket->ignoreSslErrors();
emit q->connected();
}
// ------------------ end private ---------------------------//
Socket::Socket( QObject *parent )
: QObject( parent ), d( new SocketPrivate( this ) )
{
d->socket = 0;
d->port = 0;
d->secure = false;
kDebug();
}
Socket::~Socket()
{
kDebug();
delete d;
}
void Socket::reconnect()
{
kDebug() << "Connecting to:" << d->server << ":" << d->port;
#ifdef comm_debug
// kDebug() << d->protocol;
#endif
if ( d->socket ) {
return;
}
d->socket =
static_cast<QSslSocket *>( KSocketFactory::connectToHost( d->protocol, d->server,
d->port, this ) );
d->socket->setProtocol( QSsl::AnyProtocol );
connect( d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
SLOT(slotStateChanged(QAbstractSocket::SocketState)) );
connect( d->socket, SIGNAL(modeChanged(QSslSocket::SslMode)),
SLOT(slotModeChanged(QSslSocket::SslMode)) );
connect( d->socket, SIGNAL(connected()), SLOT(slotConnected()) );
connect( d->socket, SIGNAL(readyRead()), SLOT(slotSocketRead()) );
connect( d->socket, SIGNAL(encrypted()), SIGNAL(connected()) );
connect( d->socket, SIGNAL(sslErrors(QList<QSslError>)),
SLOT(slotSslErrors(QList<QSslError>)) );
}
void Socket::write( const QString &text )
{
// kDebug();
// Eat things in the queue when there is no connection. We need
// to get a connection first don't we...
if ( !d->socket || !available() ) {
return;
}
QByteArray cs = ( text + QLatin1String( "\r\n" ) ).toLatin1();
#ifdef comm_debug
kDebug() << "C :" << cs;
#endif
d->socket->write( cs.data(), cs.size() );
}
bool Socket::available()
{
// kDebug();
bool ok = d->socket && d->socket->state() == QAbstractSocket::ConnectedState;
return ok;
}
void Socket::startTLS()
{
kDebug() << objectName();
d->socket->setProtocol( QSsl::TlsV1 );
d->socket->startClientEncryption();
}
void Socket::setProtocol( const QString &proto )
{
d->protocol = proto;
}
void Socket::setServer( const QString &server )
{
d->server = server;
}
void Socket::setPort( int port )
{
d->port = port;
}
void Socket::setSecure( bool what )
{
d->secure = what;
}
#include "moc_socket.cpp"