Commit eee98ff0 authored by Pali Rohár's avatar Pali Rohár

Update libiris from https://github.com/psi-im/iris.git commit...

Update libiris from https://github.com/psi-im/iris.git commit f8f13444c87048b18cc374a493424f36f5e5d489
parent 5d236087
#include "../../src/xmpp/xmpp-im/xmpp_caps.h"
...@@ -3,8 +3,9 @@ DEPENDPATH += $$PWD/../.. ...@@ -3,8 +3,9 @@ DEPENDPATH += $$PWD/../..
HEADERS += \ HEADERS += \
$$PWD/randomnumbergenerator.h \ $$PWD/randomnumbergenerator.h \
$$PWD/randrandomnumbergenerator.h $$PWD/randrandomnumbergenerator.h \
$$PWD/timezone.h
SOURCES += \ SOURCES += \
$$PWD/randomnumbergenerator.cpp $$PWD/randomnumbergenerator.cpp \
$$PWD/timezone.cpp
/*
* Copyright (C) Psi Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <QtGlobal>
#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
#include <QByteArray>
#include <QTime>
#ifdef Q_OS_UNIX
#include <time.h>
#endif
#ifdef Q_OS_WIN
#include <windows.h>
#endif
#else
#include <QTimeZone>
#endif
#include "timezone.h"
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
static bool inited = false;
static int timezone_offset_;
static QString timezone_str_;
static void init()
{
#if defined(Q_OS_UNIX)
time_t x;
time(&x);
char str[256];
char fmt[32];
int size;
strcpy(fmt, "%z");
size = strftime(str, 256, fmt, localtime(&x));
if(size && strncmp(fmt, str, size)) {
timezone_offset_ = QByteArray::fromRawData(str + 1, 2).toInt() * 60 + QByteArray::fromRawData(str + 3, 2).toInt();
if(str[0] == '-')
timezone_offset_ = -timezone_offset_;
}
strcpy(fmt, "%Z");
strftime(str, 256, fmt, localtime(&x));
if(strcmp(fmt, str))
timezone_str_ = str;
#elif defined(Q_OS_WIN)
TIME_ZONE_INFORMATION i;
memset(&i, 0, sizeof(i));
bool inDST = (GetTimeZoneInformation(&i) == TIME_ZONE_ID_DAYLIGHT);
int bias = i.Bias;
if(inDST)
bias += i.DaylightBias;
timezone_offset_ = -bias;
timezone_str_ = "";
for(int n = 0; n < 32; ++n) {
int w = inDST ? i.DaylightName[n] : i.StandardName[n];
if(w == 0)
break;
timezone_str_ += QChar(w);
}
#else
qWarning("Failed to properly init timezone data. Use UTC offset instead");
inited = true;
timezone_offset_ = 0;
timezone_str_ = QLatin1String("N/A");
#endif
}
#endif
int TimeZone::offsetFromUtc()
{
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
if (!inited) {
init();
}
return timezone_offset_;
#else
return QTimeZone::systemTimeZone().offsetFromUtc(QDateTime::currentDateTime());
#endif
}
QString TimeZone::abbreviation()
{
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
return timezone_str_;
#else
return QTimeZone::systemTimeZone().abbreviation(QDateTime::currentDateTime());
#endif
}
int TimeZone::tzdToInt(const QString &tzd)
{
int tzoSign = 1;
if (tzd.startsWith('Z')) {
return 0;
} else if (tzd.startsWith('+') || tzd.startsWith('-')) {
QTime time = QTime::fromString(tzd.mid(1), "hh:mm");
if (time.isValid()) {
if (tzd[0] == '-') {
tzoSign = -1;
}
return tzoSign * (time.hour() * 60 + time.second());
}
}
return -1; /* we don't have -1 sec offset. and usually the value is common for errors */
}
/**
* \fn int TimeZone::timezoneOffset()
* \brief Local timezone offset in minutes.
*/
/**
* \fn QString TimeZone::timezoneString()
* \brief Local timezone name.
*/
/*
* Copyright (C) Psi Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef IRIS_TIMEZONE_H
#define IRIS_TIMEZONE_H
#include <QObject>
class TimeZone
{
public:
static int offsetFromUtc();
static QString abbreviation();
static int tzdToInt(const QString &tzd);
};
#endif // IRIS_TIMEZONE_H
...@@ -724,6 +724,11 @@ public: ...@@ -724,6 +724,11 @@ public:
in->pause(true); in->pause(true);
reader->parse(in, true); reader->parse(in, true);
in->pause(false); in->pause(false);
} else {
reader = 0;
handler = 0;
in = 0;
doc = 0;
} }
} }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include "td.h" #include "td.h"
#endif #endif
//#define SM_DEBUG //#define IRIS_SM_DEBUG
using namespace XMPP; using namespace XMPP;
...@@ -661,12 +661,12 @@ void CoreProtocol::sendStanza(const QDomElement &e, bool notify) { ...@@ -661,12 +661,12 @@ void CoreProtocol::sendStanza(const QDomElement &e, bool notify) {
if (notify) qDebug() << "Want notification for stanza"; if (notify) qDebug() << "Want notification for stanza";
#endif #endif
sm_send_queue.push_back(qMakePair(e, notify)); sm_send_queue.push_back(qMakePair(e, notify));
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qDebug() << "sm_send_queue: "; qDebug() << "sm_send_queue: ";
#endif #endif
for (QList<QPair<QDomElement, bool> >::iterator i = sm_send_queue.begin(); i != sm_send_queue.end(); ++i) { for (QList<QPair<QDomElement, bool> >::iterator i = sm_send_queue.begin(); i != sm_send_queue.end(); ++i) {
QPair<QDomElement, bool> entry = *i; QPair<QDomElement, bool> entry = *i;
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qDebug() << "\t" << entry.first.tagName() << " : " << entry.second; qDebug() << "\t" << entry.first.tagName() << " : " << entry.second;
#endif #endif
} }
...@@ -951,14 +951,14 @@ bool CoreProtocol::streamManagementHandleStanza(const QDomElement &e) ...@@ -951,14 +951,14 @@ bool CoreProtocol::streamManagementHandleStanza(const QDomElement &e)
qulonglong last_handled_id = getSMLastHandledId(); qulonglong last_handled_id = getSMLastHandledId();
QDomElement e = doc.createElementNS(NS_STREAM_MANAGEMENT, "a"); QDomElement e = doc.createElementNS(NS_STREAM_MANAGEMENT, "a");
e.setAttribute("h", last_handled_id); e.setAttribute("h", last_handled_id);
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Stream Management: Sending acknowledgment with h=" << last_handled_id; qWarning() << "Stream Management: Sending acknowledgment with h=" << last_handled_id;
#endif #endif
send(e); send(e);
event = ESend; event = ESend;
return true; return true;
} else if (s == "a") { } else if (s == "a") {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Received ack response from server"; qWarning() << "Received ack response from server";
#endif #endif
processSMAcknowlegement(e.attribute("h").toULong()); processSMAcknowlegement(e.attribute("h").toULong());
...@@ -976,7 +976,7 @@ unsigned long CoreProtocol::getNewSMId() { ...@@ -976,7 +976,7 @@ unsigned long CoreProtocol::getNewSMId() {
sm_receive_queue.push_back(qMakePair(sm_id, false)); sm_receive_queue.push_back(qMakePair(sm_id, false));
sm_receive_count++; sm_receive_count++;
if (sm_receive_count == (unsigned long)-1) sm_receive_count = 0; /* why do we skip -1? */ if (sm_receive_count == (unsigned long)-1) sm_receive_count = 0; /* why do we skip -1? */
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Current SM id: " << sm_id; qWarning() << "Current SM id: " << sm_id;
#endif #endif
return sm_id; return sm_id;
...@@ -1006,19 +1006,19 @@ void CoreProtocol::markStanzaHandled(unsigned long id) { ...@@ -1006,19 +1006,19 @@ void CoreProtocol::markStanzaHandled(unsigned long id) {
return; return;
} }
} }
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Stream Management: Higher level client marked unknown stanza handled!"; qWarning() << "Stream Management: Higher level client marked unknown stanza handled!";
#endif #endif
} }
void CoreProtocol::markLastMessageStanzaAcked() { void CoreProtocol::markLastMessageStanzaAcked() {
if (sm_receive_queue.isEmpty()) { if (sm_receive_queue.isEmpty()) {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Stream Management: Higher level client marked unexistant stanza as acked."; qWarning() << "Stream Management: Higher level client marked unexistant stanza as acked.";
#endif #endif
return; return;
} }
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Previous list: " << sm_receive_queue; qWarning() << "Previous list: " << sm_receive_queue;
#endif #endif
for(QList<QPair<unsigned long, bool> >::Iterator it = sm_receive_queue.begin(); it != sm_receive_queue.end(); ++it ) { for(QList<QPair<unsigned long, bool> >::Iterator it = sm_receive_queue.begin(); it != sm_receive_queue.end(); ++it ) {
...@@ -1034,7 +1034,7 @@ bool CoreProtocol::isStreamManagementActive() const { ...@@ -1034,7 +1034,7 @@ bool CoreProtocol::isStreamManagementActive() const {
} }
void CoreProtocol::requestSMAcknowlegement() { void CoreProtocol::requestSMAcknowlegement() {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qDebug() << "Now I'd request acknowledgement from the server."; qDebug() << "Now I'd request acknowledgement from the server.";
#endif #endif
sendDirect(QString("<r xmlns='" NS_STREAM_MANAGEMENT "'/>")); sendDirect(QString("<r xmlns='" NS_STREAM_MANAGEMENT "'/>"));
...@@ -1046,7 +1046,7 @@ int CoreProtocol::getNotableStanzasAcked() { ...@@ -1046,7 +1046,7 @@ int CoreProtocol::getNotableStanzasAcked() {
} }
ClientStream::SMState CoreProtocol::getSMState() const { ClientStream::SMState CoreProtocol::getSMState() const {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qDebug("\tCoreProtocol::getSMState()"); qDebug("\tCoreProtocol::getSMState()");
#endif #endif
ClientStream::SMState state; ClientStream::SMState state;
...@@ -1539,6 +1539,12 @@ bool CoreProtocol::normalStep(const QDomElement &e) ...@@ -1539,6 +1539,12 @@ bool CoreProtocol::normalStep(const QDomElement &e)
f.hosts += l.item(n).toElement().text(); f.hosts += l.item(n).toElement().text();
hosts += f.hosts; hosts += f.hosts;
} }
QDomElement caps = e.elementsByTagNameNS(NS_CAPS, "c").item(0).toElement();
if(!caps.isNull()) {
f.capsNode = caps.attribute("node");
f.capsVersion = caps.attribute("ver");
f.capsAlgo = caps.attribute("hash");
}
// check for XEP-0198 support if we are already authed // check for XEP-0198 support if we are already authed
if (sasl_authed) { if (sasl_authed) {
...@@ -1894,17 +1900,17 @@ bool CoreProtocol::normalStep(const QDomElement &e) ...@@ -1894,17 +1900,17 @@ bool CoreProtocol::normalStep(const QDomElement &e)
} }
} }
else if(step == GetSMResponse) { else if(step == GetSMResponse) {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "HandleSM: step"; qWarning() << "HandleSM: step";
#endif #endif
if (e.namespaceURI() == NS_STREAM_MANAGEMENT) { if (e.namespaceURI() == NS_STREAM_MANAGEMENT) {
if (e.localName() == "enabled") { if (e.localName() == "enabled") {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qWarning() << "Stream Management enabled"; qWarning() << "Stream Management enabled";
#endif #endif
sm_started = true; sm_started = true;
if (e.attribute("resume", "false") == "true" || e.attribute("resume", "false") == "1") { if (e.attribute("resume", "false") == "true" || e.attribute("resume", "false") == "1") {
#ifdef SM_DEBUG #ifdef IRIS_SM_DEBUG
qDebug("\tResumption Supported"); qDebug("\tResumption Supported");
#endif #endif
sm_resumption_supported = true; sm_resumption_supported = true;
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#define PROTOCOL_H #define PROTOCOL_H
#include <QObject> #include <QObject>
//Added by qt3to4:
#include <QList> #include <QList>
#include <QPair> #include <QPair>
#include <QTimer> #include <QTimer>
...@@ -40,6 +39,7 @@ ...@@ -40,6 +39,7 @@
#define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session" #define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session"
#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" #define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind" #define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind"
#define NS_CAPS "http://jabber.org/protocol/caps"
#define NS_COMPRESS_FEATURE "http://jabber.org/features/compress" #define NS_COMPRESS_FEATURE "http://jabber.org/features/compress"
#define NS_COMPRESS_PROTOCOL "http://jabber.org/protocol/compress" #define NS_COMPRESS_PROTOCOL "http://jabber.org/protocol/compress"
#define NS_HOSTS "http://barracuda.com/xmppextensions/hosts" #define NS_HOSTS "http://barracuda.com/xmppextensions/hosts"
...@@ -66,6 +66,9 @@ namespace XMPP ...@@ -66,6 +66,9 @@ namespace XMPP
QStringList sasl_mechs; QStringList sasl_mechs;
QStringList compression_mechs; QStringList compression_mechs;
QStringList hosts; QStringList hosts;
QString capsVersion;
QString capsNode;
QString capsAlgo;
}; };
class BasicProtocol : public XmlProtocol class BasicProtocol : public XmlProtocol
......
...@@ -200,6 +200,7 @@ public: ...@@ -200,6 +200,7 @@ public:
QString connectHost; QString connectHost;
int minimumSSF, maximumSSF; int minimumSSF, maximumSSF;
QString sasl_mech; QString sasl_mech;
QMap<QString,QString> mechProviders; // mech to provider map
bool doBinding; bool doBinding;
bool in_rrsig; bool in_rrsig;
...@@ -437,6 +438,24 @@ void ClientStream::continueAfterParams() ...@@ -437,6 +438,24 @@ void ClientStream::continueAfterParams()
} }
} }
void ClientStream::setSaslMechanismProvider(const QString &m, const QString &p)
{
d->mechProviders.insert(m, p);
}
QString ClientStream::saslMechanismProvider(const QString &m) const
{
return d->mechProviders.value(m);
}
QCA::Provider::Context *ClientStream::currentSASLContext() const
{
if (d->sasl) {
return d->sasl->context();
}
return 0;
}
void ClientStream::setSCRAMStoredSaltedHash(const QString &s) { void ClientStream::setSCRAMStoredSaltedHash(const QString &s) {
QCA::SASLContext *context = (QCA::SASLContext *)(d->sasl->context()); QCA::SASLContext *context = (QCA::SASLContext *)(d->sasl->context());
if (context) { if (context) {
...@@ -925,7 +944,8 @@ void ClientStream::srvProcessNext() ...@@ -925,7 +944,8 @@ void ClientStream::srvProcessNext()
void ClientStream::doReadyRead() void ClientStream::doReadyRead()
{ {
//QGuardedPtr<QObject> self = this; //QGuardedPtr<QObject> self = this;
readyRead(); if (isActive())
emit readyRead();
//if(!self) //if(!self)
// return; // return;
//d->in_rrsig = false; //d->in_rrsig = false;
...@@ -1162,7 +1182,21 @@ bool ClientStream::handleNeed() ...@@ -1162,7 +1182,21 @@ bool ClientStream::handleNeed()
QCA::setProviderPriority("simplesasl", 10); QCA::setProviderPriority("simplesasl", 10);
} }
d->sasl = new QCA::SASL(); QStringList ml;
if(!d->sasl_mech.isEmpty())
ml += d->sasl_mech;
else
ml = d->client.features.sasl_mechs;
QString saslProvider;
foreach (const QString &mech, d->mechProviders.keys()) {
if (ml.contains(mech)) {
saslProvider = d->mechProviders[mech];
break;
}
}
d->sasl = new QCA::SASL(0, saslProvider);
connect(d->sasl, SIGNAL(clientStarted(bool,QByteArray)), SLOT(sasl_clientFirstStep(bool,QByteArray))); connect(d->sasl, SIGNAL(clientStarted(bool,QByteArray)), SLOT(sasl_clientFirstStep(bool,QByteArray)));
connect(d->sasl, SIGNAL(nextStep(QByteArray)), SLOT(sasl_nextStep(QByteArray))); connect(d->sasl, SIGNAL(nextStep(QByteArray)), SLOT(sasl_nextStep(QByteArray)));
connect(d->sasl, SIGNAL(needParams(QCA::SASL::Params)), SLOT(sasl_needParams(QCA::SASL::Params))); connect(d->sasl, SIGNAL(needParams(QCA::SASL::Params)), SLOT(sasl_needParams(QCA::SASL::Params)));
...@@ -1187,12 +1221,6 @@ bool ClientStream::handleNeed() ...@@ -1187,12 +1221,6 @@ bool ClientStream::handleNeed()
auth_flags = (QCA::SASL::AuthFlags) (auth_flags | QCA::SASL::RequireMutualAuth); auth_flags = (QCA::SASL::AuthFlags) (auth_flags | QCA::SASL::RequireMutualAuth);
d->sasl->setConstraints(auth_flags,d->minimumSSF,d->maximumSSF); d->sasl->setConstraints(auth_flags,d->minimumSSF,d->maximumSSF);
QStringList ml;
if(!d->sasl_mech.isEmpty())
ml += d->sasl_mech;
else
ml = d->client.features.sasl_mechs;
#ifdef IRIS_SASLCONNECTHOST #ifdef IRIS_SASLCONNECTHOST
d->sasl->startClient("xmpp", QUrl::toAce(d->connectHost), ml, QCA::SASL::AllowClientSendFirst); d->sasl->startClient("xmpp", QUrl::toAce(d->connectHost), ml, QCA::SASL::AllowClientSendFirst);
#else #else
...@@ -1427,6 +1455,11 @@ QStringList ClientStream::hosts() const ...@@ -1427,6 +1455,11 @@ QStringList ClientStream::hosts() const
return d->client.hosts; return d->client.hosts;
} }
const StreamFeatures &ClientStream::streamFeatures() const
{
return d->client.features;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Debug // Debug
......
...@@ -36,6 +36,7 @@ namespace XMPP ...@@ -36,6 +36,7 @@ namespace XMPP
{ {
class TLSHandler; class TLSHandler;
class Connector; class Connector;
class StreamFeatures;
class ClientStream : public Stream class ClientStream : public Stream
{ {
...@@ -119,6 +120,9 @@ namespace XMPP ...@@ -119,6 +120,9 @@ namespace XMPP
void setRealm(const QString &s); void setRealm(const QString &s);
void setAuthzid(const QString &s); void setAuthzid(const QString &s);
void continueAfterParams(); void continueAfterParams();
void setSaslMechanismProvider(const QString &m, const QString &p);
QString saslMechanismProvider(const QString &m) const;
QCA::Provider::Context *currentSASLContext() const;
void setSCRAMStoredSaltedHash(const QString &s); void setSCRAMStoredSaltedHash(const QString &s);
const QString getSCRAMStoredSaltedHash(); const QString getSCRAMStoredSaltedHash();
...@@ -172,6 +176,8 @@ namespace XMPP ...@@ -172,6 +176,8 @@ namespace XMPP
// barracuda extension // barracuda extension
QStringList hosts() const; QStringList hosts() const;
const StreamFeatures &streamFeatures() const;
signals: signals:
void connected(); void connected();
void securityLayerActivated(int); void securityLayerActivated(int);
......
...@@ -18,9 +18,6 @@ ...@@ -18,9 +18,6 @@
* *
*/ */
#include "im.h"
#include "safedelete.h"
//! \class XMPP::Client client.h //! \class XMPP::Client client.h
//! \brief Communicates with the XMPP network. Start here. //! \brief Communicates with the XMPP network. Start here.
//! //!
...@@ -69,34 +66,22 @@ ...@@ -69,34 +66,22 @@
//! } //! }
//! \endcode //! \endcode
#include <stdarg.h> #include <QObject>
#include <qobject.h>
#include <QMap> #include <QMap>
#include <qtimer.h> #include <QTimer>
#include <qpointer.h>