bool LastActivityManager::handleStanza (const QDomElement& elem) { if (elem.tagName () != "iq") return false; const QDomElement& query = elem.firstChildElement ("query"); if (query.namespaceURI () != NsLastActivity) return false; const QString& from = elem.attribute ("from"); if (elem.attribute ("type") == "get") { IPluginsManager *pMgr = Core::Instance () .GetProxy ()->GetPluginsManager (); ILastActivityProvider *prov = pMgr-> GetAllCastableTo<ILastActivityProvider*> ().value (0); if (!prov) return false; QXmppIq iq = CreateIq (from, prov->GetInactiveSeconds ()); iq.setType (QXmppIq::Result); iq.setId (elem.attribute ("id")); client ()->sendPacket (iq); } else if (elem.attribute ("type") == "result" && query.hasAttribute ("seconds")) emit gotLastActivity (from, query.attribute ("seconds").toInt ()); return true; }
int QXmppCallWebrtcManager::SendAck(QXmppWebRtcIq iq) { QXmppIq ack; ack.setId(iq.id()); ack.setTo(iq.from()); ack.setType(QXmppIq::Result); return client()->sendPacket(ack); }
void AdHocCommandServer::SendCompleted (const QDomElement& sourceElem, const QString& node, const QString& sessionId) { QXmppElement elem; elem.setTagName ("command"); elem.setAttribute ("xmlns", NsCommands); elem.setAttribute ("node", node); elem.setAttribute ("status", "completed"); elem.setAttribute ("sessionid", sessionId); QXmppIq iq; iq.setTo (sourceElem.attribute ("from")); iq.setId (sourceElem.attribute ("id")); iq.setType (QXmppIq::Result); iq.setExtensions (QXmppElementList () << elem); Conn_->GetClient ()->sendPacket (iq); }
bool LegacyEntityTimeExt::handleStanza (const QDomElement& elem) { if (elem.tagName () != "iq" || elem.attribute ("type") != "get") return false; if (elem.firstChildElement ("query").namespaceURI () != NsLegacyEntityTime) return false; const QString& from = elem.attribute ("from"); if (from.isEmpty ()) return false; const QDateTime& date = QDateTime::currentDateTime ().toUTC (); QXmppElement utcElem; utcElem.setTagName ("utc"); utcElem.setValue (date.toString ("yyyyMMddThh:mm:ss")); const QString& displayStr = "Your client/bot sucks since it " "uses the long-deprecated XEP-0090. Upgrade your code. " "Ah, and, regarding your question, it's " + QDateTime::currentDateTime ().toString () + " here"; QXmppElement displayElem; displayElem.setTagName ("display"); displayElem.setValue (displayStr); QXmppElement queryElem; queryElem.setTagName ("query"); queryElem.setAttribute ("xmlns", NsLegacyEntityTime); queryElem.appendChild (utcElem); queryElem.appendChild (displayElem); QXmppIq iq (QXmppIq::Result); iq.setTo (from); iq.setId (elem.attribute ("id")); iq.setExtensions (QXmppElementList () << queryElem); client ()->sendPacket (iq); return true; }
bool XmppServerProxy65::handleStanza(const QDomElement &element) { if (element.attribute("to") != d->jid) return false; if (element.tagName() == "iq" && QXmppDiscoveryIq::isDiscoveryIq(element)) { QXmppDiscoveryIq discoIq; discoIq.parse(element); if (discoIq.type() == QXmppIq::Get) { QXmppDiscoveryIq responseIq; responseIq.setTo(discoIq.from()); responseIq.setFrom(discoIq.to()); responseIq.setId(discoIq.id()); responseIq.setType(QXmppIq::Result); responseIq.setQueryType(discoIq.queryType()); if (discoIq.queryType() == QXmppDiscoveryIq::InfoQuery) { QStringList features = QStringList() << ns_disco_info << ns_disco_items << ns_bytestreams; QList<QXmppDiscoveryIq::Identity> identities; QXmppDiscoveryIq::Identity identity; identity.setCategory("proxy"); identity.setType("bytestreams"); identity.setName("SOCKS5 Bytestreams"); identities.append(identity); responseIq.setFeatures(features); responseIq.setIdentities(identities); } server()->sendPacket(responseIq); return true; } } else if (element.tagName() == "iq" && QXmppByteStreamIq::isByteStreamIq(element)) { QXmppByteStreamIq bsIq; bsIq.parse(element); if (bsIq.type() == QXmppIq::Get) { // request for the proxy's network address if (d->allowedDomains.contains(QXmppUtils::jidToDomain(bsIq.from()))) { QXmppByteStreamIq responseIq; responseIq.setType(QXmppIq::Result); responseIq.setTo(bsIq.from()); responseIq.setFrom(bsIq.to()); responseIq.setId(bsIq.id()); QList<QXmppByteStreamIq::StreamHost> streamHosts; QXmppByteStreamIq::StreamHost streamHost; streamHost.setJid(d->jid); streamHost.setHost(d->hostAddress.toString()); streamHost.setPort(d->port); streamHosts.append(streamHost); responseIq.setStreamHosts(streamHosts); server()->sendPacket(responseIq); } else { QXmppIq responseIq; responseIq.setType(QXmppIq::Error); responseIq.setTo(bsIq.from()); responseIq.setFrom(bsIq.to()); responseIq.setId(bsIq.id()); responseIq.setError(QXmppStanza::Error(QXmppStanza::Error::Auth, QXmppStanza::Error::Forbidden)); server()->sendPacket(responseIq); } } else if (bsIq.type() == QXmppIq::Set) { QString hash = streamHash(bsIq.sid(), bsIq.from(), bsIq.activate()); QTcpSocketPair *pair = d->pairs.value(hash); QXmppIq responseIq; responseIq.setTo(bsIq.from()); responseIq.setFrom(bsIq.to()); responseIq.setId(bsIq.id()); if (pair && d->allowedDomains.contains(QXmppUtils::jidToDomain(bsIq.from()))) { if (pair->activate()) { info(QString("Activated connection %1 by %2").arg(hash, bsIq.from())); responseIq.setType(QXmppIq::Result); } else { warning(QString("Failed to activate connection %1 by %2").arg(hash, bsIq.from())); responseIq.setType(QXmppIq::Error); } } else { warning(QString("Not activating connection %1 by %2").arg(hash, bsIq.from())); responseIq.setType(QXmppIq::Error); } server()->sendPacket(responseIq); } return true; } return false; }
bool XmppServerPrivate::handleStanza(const QDomElement &element) { const QString to = element.attribute("to"); if (QXmppUtils::jidToDomain(to) != server()->domain()) return false; if (element.tagName() == "iq" && PrivateStorageIq::isPrivateStorageIq(element)) { PrivateStorageIq request; request.parse(element); if (request.type() == QXmppIq::Result) return true; // check the namespace is valid const QString xmlns = request.payload().attribute("xmlns"); if (xmlns.isEmpty()) { QXmppIq response; response.setId(request.id()); response.setTo(request.from()); response.setType(QXmppIq::Error); server()->sendPacket(response); return true; } const QString bareFrom = QXmppUtils::jidToBareJid(request.from()); QDjangoQuerySet<PrivateStorage> qs; qs = qs.filter(QDjangoWhere("jid", QDjangoWhere::Equals, bareFrom)); if (request.type() == QXmppIq::Get) { PrivateStorageIq response; response.setId(request.id()); response.setTo(request.from()); response.setType(QXmppIq::Result); PrivateStorage storage; if (qs.get(QDjangoWhere("xmlns", QDjangoWhere::Equals, xmlns), &storage)) { QDomDocument doc; doc.setContent(storage.data()); response.setPayload(doc.documentElement()); } else { response.setPayload(request.payload()); } server()->sendPacket(response); } else if (request.type() == QXmppIq::Set) { PrivateStorage storage; if (!qs.get(QDjangoWhere("xmlns", QDjangoWhere::Equals, xmlns), &storage)) { storage.setJid(bareFrom); storage.setXmlns(xmlns); } storage.setXml(request.payload()); storage.save(); // reply QXmppIq response; response.setId(request.id()); response.setTo(request.from()); response.setType(QXmppIq::Result); server()->sendPacket(response); } return true; } return false; }
void QXmppIncomingClient::handleStanza (const QDomElement &nodeRecv) { const QString ns = nodeRecv.namespaceURI(); if (d->idleTimer->interval()) d->idleTimer->start(); if (ns == ns_tls && nodeRecv.tagName() == QLatin1String ("starttls")) { sendData ("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); socket()->flush(); socket()->startServerEncryption(); return; } else if (ns == ns_sasl) { if (!d->passwordChecker) { warning ("Cannot perform authentication, no password checker"); sendPacket (QXmppSaslFailure ("temporary-auth-failure")); disconnectFromHost(); return; } if (nodeRecv.tagName() == QLatin1String ("auth")) { QXmppSaslAuth auth; auth.parse (nodeRecv); d->saslServer = QXmppSaslServer::create (auth.mechanism(), this); if (!d->saslServer) { sendPacket (QXmppSaslFailure ("invalid-mechanism")); disconnectFromHost(); return; } d->saslServer->setRealm (d->domain.toUtf8()); QByteArray challenge; QXmppSaslServer::Response result = d->saslServer->respond (auth.value(), challenge); if (result == QXmppSaslServer::InputNeeded) { // check credentials d->checkCredentials (auth.value()); } else if (result == QXmppSaslServer::Challenge) sendPacket (QXmppSaslChallenge (challenge)); else { // FIXME: what condition? sendPacket (QXmppSaslFailure()); disconnectFromHost(); return; } } else if (nodeRecv.tagName() == QLatin1String ("response")) { QXmppSaslResponse response; response.parse (nodeRecv); if (!d->saslServer) { warning ("SASL response received, but no mechanism selected"); sendPacket (QXmppSaslFailure()); disconnectFromHost(); return; } QByteArray challenge; QXmppSaslServer::Response result = d->saslServer->respond (response.value(), challenge); if (result == QXmppSaslServer::InputNeeded) { // check credentials d->checkCredentials (response.value()); } else if (result == QXmppSaslServer::Succeeded) { // authentication succeeded d->jid = QString ("%1@%2").arg (d->saslServer->username(), d->domain); info (QString ("Authentication succeeded for '%1' from %2").arg (d->jid, d->origin())); updateCounter ("incoming-client.auth.success"); sendPacket (QXmppSaslSuccess()); handleStart(); } else { // FIXME: what condition? sendPacket (QXmppSaslFailure()); disconnectFromHost(); } } } else if (ns == ns_client) { if (nodeRecv.tagName() == QLatin1String ("iq")) { const QString type = nodeRecv.attribute ("type"); if (QXmppBindIq::isBindIq (nodeRecv) && type == QLatin1String ("set")) { QXmppBindIq bindSet; bindSet.parse (nodeRecv); d->resource = bindSet.resource().trimmed(); if (d->resource.isEmpty()) d->resource = QXmppUtils::generateStanzaHash(); d->jid = QString ("%1/%2").arg (QXmppUtils::jidToBareJid (d->jid), d->resource); QXmppBindIq bindResult; bindResult.setType (QXmppIq::Result); bindResult.setId (bindSet.id()); bindResult.setJid (d->jid); sendPacket (bindResult); // bound emit connected(); return; } else if (QXmppSessionIq::isSessionIq (nodeRecv) && type == QLatin1String ("set")) { QXmppSessionIq sessionSet; sessionSet.parse (nodeRecv); QXmppIq sessionResult; sessionResult.setType (QXmppIq::Result); sessionResult.setId (sessionSet.id()); sessionResult.setTo (d->jid); sendPacket (sessionResult); return; } } // check the sender is legitimate const QString from = nodeRecv.attribute ("from"); if (!from.isEmpty() && from != d->jid && from != QXmppUtils::jidToBareJid (d->jid)) { warning (QString ("Received a stanza from unexpected JID %1").arg (from)); return; } // process unhandled stanzas if (nodeRecv.tagName() == QLatin1String ("iq") || nodeRecv.tagName() == QLatin1String ("message") || nodeRecv.tagName() == QLatin1String ("presence")) { QDomElement nodeFull (nodeRecv); // if the sender is empty, set it to the appropriate JID if (nodeFull.attribute ("from").isEmpty()) { if (nodeFull.tagName() == QLatin1String ("presence") && (nodeFull.attribute ("type") == QLatin1String ("subscribe") || nodeFull.attribute ("type") == QLatin1String ("subscribed"))) nodeFull.setAttribute ("from", QXmppUtils::jidToBareJid (d->jid)); else nodeFull.setAttribute ("from", d->jid); } // if the recipient is empty, set it to the local domain if (nodeFull.attribute ("to").isEmpty()) nodeFull.setAttribute ("to", d->domain); // emit stanza for processing by server emit elementReceived (nodeFull); } } }
void QXmppIncomingClient::handleStanza(const QDomElement &nodeRecv) { const QString ns = nodeRecv.namespaceURI(); if (d->idleTimer->interval()) d->idleTimer->start(); if (ns == ns_tls && nodeRecv.tagName() == "starttls") { sendData("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); socket()->flush(); socket()->startServerEncryption(); return; } else if (ns == ns_sasl) { if (nodeRecv.tagName() == "auth") { const QString mechanism = nodeRecv.attribute("mechanism"); if (mechanism == "PLAIN") { QList<QByteArray> auth = QByteArray::fromBase64(nodeRecv.text().toAscii()).split('\0'); if (auth.size() != 3) { sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><incorrect-encoding/></failure>"); disconnectFromHost(); return; } QXmppPasswordRequest request; request.setDomain(d->domain); request.setUsername(QString::fromUtf8(auth[1])); request.setPassword(QString::fromUtf8(auth[2])); if (!d->passwordChecker) { // FIXME: what type of failure? warning(QString("Cannot authenticate '%1', no password checker").arg(request.username())); sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); disconnectFromHost(); return; } QXmppPasswordReply *reply = d->passwordChecker->checkPassword(request); reply->setParent(this); reply->setProperty("__sasl_username", request.username()); connect(reply, SIGNAL(finished()), this, SLOT(onPasswordReply())); } else if (mechanism == "DIGEST-MD5") { // generate nonce d->saslDigest.setNonce(QXmppSaslDigestMd5::generateNonce()); d->saslDigest.setQop("auth"); d->saslStep = 1; QMap<QByteArray, QByteArray> challenge; challenge["nonce"] = d->saslDigest.nonce(); challenge["realm"] = d->domain.toUtf8(); challenge["qop"] = d->saslDigest.qop(); challenge["charset"] = "utf-8"; challenge["algorithm"] = "md5-sess"; const QByteArray data = QXmppSaslDigestMd5::serializeMessage(challenge).toBase64(); sendData("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + data +"</challenge>"); } else { // unsupported method sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'></failure>"); disconnectFromHost(); return; } } else if (nodeRecv.tagName() == "response") { if (d->saslStep == 1) { const QByteArray raw = QByteArray::fromBase64(nodeRecv.text().toAscii()); QMap<QByteArray, QByteArray> saslResponse = QXmppSaslDigestMd5::parseMessage(raw); // check credentials const QString username = QString::fromUtf8(saslResponse.value("username")); if (!d->passwordChecker) { // FIXME: what type of failure? warning(QString("Cannot authenticate '%1', no password checker").arg(username)); sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); disconnectFromHost(); return; } QXmppPasswordRequest request; request.setUsername(username); request.setDomain(d->domain); QXmppPasswordReply *reply = d->passwordChecker->getDigest(request); reply->setParent(this); reply->setProperty("__sasl_raw", raw); connect(reply, SIGNAL(finished()), this, SLOT(onDigestReply())); } else if (d->saslStep == 2) { // authentication succeeded d->saslStep = 3; info(QString("Authentication succeeded for '%1'").arg(d->username)); sendData("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); } } } else if (ns == ns_client) { if (nodeRecv.tagName() == "iq") { const QString type = nodeRecv.attribute("type"); if (QXmppBindIq::isBindIq(nodeRecv) && type == "set") { QXmppBindIq bindSet; bindSet.parse(nodeRecv); d->resource = bindSet.resource().trimmed(); if (d->resource.isEmpty()) d->resource = generateStanzaHash(); QXmppBindIq bindResult; bindResult.setType(QXmppIq::Result); bindResult.setId(bindSet.id()); bindResult.setJid(jid()); sendPacket(bindResult); // bound emit connected(); return; } else if (QXmppSessionIq::isSessionIq(nodeRecv) && type == "set") { QXmppSessionIq sessionSet; sessionSet.parse(nodeRecv); QXmppIq sessionResult; sessionResult.setType(QXmppIq::Result); sessionResult.setId(sessionSet.id()); sessionResult.setTo(jid()); sendPacket(sessionResult); return; } } // check the sender is legitimate const QString from = nodeRecv.attribute("from"); if (!from.isEmpty() && from != jid() && from != jidToBareJid(jid())) { warning(QString("Received a stanza from unexpected JID %1").arg(from)); return; } // process unhandled stanzas if (nodeRecv.tagName() == "iq" || nodeRecv.tagName() == "message" || nodeRecv.tagName() == "presence") { QDomElement nodeFull(nodeRecv); // if the sender is empty, set it to the appropriate JID if (nodeFull.attribute("from").isEmpty()) { if (nodeFull.tagName() == "presence" && (nodeFull.attribute("type") == "subscribe" || nodeFull.attribute("type") == "subscribed")) nodeFull.setAttribute("from", jidToBareJid(jid())); else nodeFull.setAttribute("from", jid()); } // if the recipient is empty, set it to the local domain if (nodeFull.attribute("to").isEmpty()) nodeFull.setAttribute("to", d->domain); // emit stanza for processing by server emit elementReceived(nodeFull); } } }