void QXmppIncomingClient::onPasswordReply()
{
    QXmppPasswordReply *reply = qobject_cast<QXmppPasswordReply*>(sender());
    if (!reply)
        return;
    reply->deleteLater();

    const QString username = reply->property("__sasl_username").toString();
    switch (reply->error()) {
    case QXmppPasswordReply::NoError:
        d->username = username;
        info(QString("Authentication succeeded for '%1'").arg(username));
        sendData("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
        break;
    case QXmppPasswordReply::AuthorizationError:
        warning(QString("Authentication failed for '%1'").arg(username));
        sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>");
        disconnectFromHost();
        break;
    case QXmppPasswordReply::TemporaryError:
        warning(QString("Temporary authentication failure for '%1'").arg(username));
        sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><temporary-auth-failure/></failure>");
        disconnectFromHost();
        break;
    }
}
void QXmppIncomingClient::onDigestReply()
{
    QXmppPasswordReply *reply = qobject_cast<QXmppPasswordReply *> (sender());

    if (!reply)
        return;

    reply->deleteLater();

    if (reply->error() == QXmppPasswordReply::TemporaryError)
    {
        warning (QString ("Temporary authentication failure for '%1' from %2").arg (d->saslServer->username(), d->origin()));
        updateCounter ("incoming-client.auth.temporary-auth-failure");
        sendPacket (QXmppSaslFailure ("temporary-auth-failure"));
        disconnectFromHost();
        return;
    }

    QByteArray challenge;
    d->saslServer->setPasswordDigest (reply->digest());

    QXmppSaslServer::Response result = d->saslServer->respond (reply->property ("__sasl_raw").toByteArray(), challenge);

    if (result != QXmppSaslServer::Challenge)
    {
        warning (QString ("Authentication failed for '%1' from %2").arg (d->saslServer->username(), d->origin()));
        updateCounter ("incoming-client.auth.not-authorized");
        sendPacket (QXmppSaslFailure ("not-authorized"));
        disconnectFromHost();
        return;
    }

    // send new challenge
    sendPacket (QXmppSaslChallenge (challenge));
}
void QXmppIncomingClient::onDigestReply()
{
    QXmppPasswordReply *reply = qobject_cast<QXmppPasswordReply*>(sender());
    if (!reply)
        return;
    reply->deleteLater();

    const QMap<QByteArray, QByteArray> saslResponse = QXmppSaslDigestMd5::parseMessage(reply->property("__sasl_raw").toByteArray());
    const QString username = QString::fromUtf8(saslResponse.value("username"));
    if (reply->error() == QXmppPasswordReply::TemporaryError) {
        warning(QString("Temporary authentication failure for '%1'").arg(username));
        sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><temporary-auth-failure/></failure>");
        disconnectFromHost();
        return;
    }

    d->saslDigest.setSecret(reply->digest());
    d->saslDigest.setDigestUri(saslResponse.value("digest-uri"));
    d->saslDigest.setNc(saslResponse.value("nc"));
    d->saslDigest.setCnonce(saslResponse.value("cnonce"));
    if (saslResponse.value("response") != d->saslDigest.calculateDigest(
            QByteArray("AUTHENTICATE:") + d->saslDigest.digestUri()))
    {
        sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>");
        disconnectFromHost();
        return;
    }

    // send new challenge
    d->username = username;
    d->saslStep = 2;
    QMap<QByteArray, QByteArray> challenge;
    challenge["rspauth"] = d->saslDigest.calculateDigest(
        QByteArray(":") + d->saslDigest.digestUri());
    const QByteArray data = QXmppSaslDigestMd5::serializeMessage(challenge).toBase64();
    sendData("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + data +"</challenge>");
}
void QXmppIncomingClient::onPasswordReply()
{
    QXmppPasswordReply *reply = qobject_cast<QXmppPasswordReply *> (sender());

    if (!reply)
        return;

    reply->deleteLater();

    const QString jid = QString ("%1@%2").arg (d->saslServer->username(), d->domain);

    switch (reply->error())
    {
        case QXmppPasswordReply::NoError:
            d->jid = jid;
            info (QString ("Authentication succeeded for '%1' from %2").arg (d->jid, d->origin()));
            updateCounter ("incoming-client.auth.success");
            sendPacket (QXmppSaslSuccess());
            handleStart();
            break;

        case QXmppPasswordReply::AuthorizationError:
            warning (QString ("Authentication failed for '%1' from %2").arg (jid, d->origin()));
            updateCounter ("incoming-client.auth.not-authorized");
            sendPacket (QXmppSaslFailure ("not-authorized"));
            disconnectFromHost();
            break;

        case QXmppPasswordReply::TemporaryError:
            warning (QString ("Temporary authentication failure for '%1' from %2").arg (jid, d->origin()));
            updateCounter ("incoming-client.auth.temporary-auth-failure");
            sendPacket (QXmppSaslFailure ("temporary-auth-failure"));
            disconnectFromHost();
            break;
    }
}