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>");
}