Exemple #1
0
bool StartTLSFeature::xmppStanzaIn(IXmppStream *AXmppStream, Stanza &AStanza, int AOrder)
{
	if (AXmppStream==FXmppStream && AOrder==XSHO_XMPP_FEATURE)
	{
		FXmppStream->removeXmppStanzaHandler(XSHO_XMPP_FEATURE,this);
		if (AStanza.tagName() == "proceed")
		{
			if (FXmppStream->connection()->startEncryption())
			{
				LOG_STRM_INFO(FXmppStream->streamJid(),"Starting StartTLS encryption");
				connect(FXmppStream->connection()->instance(),SIGNAL(encrypted()),SLOT(onConnectionEncrypted()));
			}
			else
			{
				LOG_STRM_ERROR(FXmppStream->streamJid(),"Failed to negotiate StartTLS encryption: Handshake not started");
				emit error(XmppError(IERR_STARTTLS_NOT_STARTED));
			}
		}
		else if (AStanza.tagName() == "failure")
		{
			LOG_STRM_WARNING(FXmppStream->streamJid(),"Failed to negotiate StartTLS encryption: Negotiation failed");
			emit error(XmppError(IERR_STARTTLS_NEGOTIATION_FAILED));
		}
		else
		{
			LOG_STRM_WARNING(FXmppStream->streamJid(),"Failed to negotiate StartTLS encryption: Invalid responce");
			emit error(XmppError(IERR_STARTTLS_INVALID_RESPONCE));
		}
		return true;
	}
	return false;
}
Exemple #2
0
void CompressFeature::processData(QByteArray &AData, bool ADataOut)
{
	if (AData.size() > 0)
	{
		int ret;
		int dataPosOut = 0;

		z_streamp zstream = ADataOut ? &FDefStruc : &FInfStruc;
		zstream->avail_in = AData.size();
		zstream->next_in = (Bytef *)(AData.constData());

		do
		{
			zstream->avail_out = FOutBuffer.capacity() - dataPosOut;
			zstream->next_out = (Bytef *)(FOutBuffer.data() + dataPosOut);
			ret = ADataOut ? deflate(zstream,Z_SYNC_FLUSH) : inflate(zstream,Z_SYNC_FLUSH);

			if (ret != Z_OK)
				REPORT_ERROR(QString("Failed to deflate/inflate data, ZLib=%1: %2").arg(ZLIB_VERSION).arg(ret));

			switch (ret)
			{
			case Z_OK:
				dataPosOut = FOutBuffer.capacity() - zstream->avail_out;
				if (zstream->avail_out == 0)
					FOutBuffer.reserve(FOutBuffer.capacity() + CHUNK);
				break;
			case Z_STREAM_ERROR:
				emit error(XmppError(IERR_COMPRESS_INVALID_COMPRESSION_LEVEL));
				break;
			case Z_DATA_ERROR:
				emit error(XmppError(IERR_COMPRESS_INVALID_DEFLATE_DATA));
				break;
			case Z_MEM_ERROR:
				emit error(XmppError(IERR_COMPRESS_OUT_OF_MEMORY));
				break;
			case Z_VERSION_ERROR:
				emit error(XmppError(IERR_COMPRESS_VERSION_MISMATCH));
				break;
			default:
				emit error(XmppError(IERR_COMPRESS_UNKNOWN_ERROR,tr("Error code: %1").arg(ret)));
			}
		} while (ret == Z_OK && zstream->avail_out == 0);
		
		AData.resize(dataPosOut);
		memcpy(AData.data(),FOutBuffer.constData(),dataPosOut);
	}
}
Exemple #3
0
bool InBandStream::sendNextPaket(bool AFlush)
{
	bool sent = false;
	if (isOpen() && FDataIqRequestId.isEmpty() && (bytesToWrite()>=FBlockSize || AFlush))
	{
		FThreadLock.lockForWrite();
		QByteArray data = FWriteBuffer.read(FBlockSize);
		FThreadLock.unlock();

		if (!data.isEmpty())
		{
			if (FStanzaProcessor)
			{
				Stanza paket(FStanzaType==StanzaMessage ? STANZA_KIND_MESSAGE : STANZA_KIND_IQ);
				paket.setTo(FContactJid.full()).setUniqueId();

				QDomElement dataElem = paket.addElement("data",NS_INBAND_BYTESTREAMS);
				dataElem.setAttribute("sid",FStreamId);
				dataElem.setAttribute("seq",FSeqOut);
				dataElem.appendChild(paket.createTextNode(QString::fromUtf8(data.toBase64())));

				if (FStanzaType == StanzaMessage)
				{
					QDomElement ampElem = paket.addElement("amp","http://jabber.org/protocol/amp");
					QDomElement ruleElem = ampElem.appendChild(paket.createElement("rule")).toElement();
					ruleElem.setAttribute("condition","deliver");
					ruleElem.setAttribute("value","stored");
					ruleElem.setAttribute("action","error");
					ruleElem = ampElem.appendChild(paket.createElement("rule")).toElement();
					ruleElem.setAttribute("condition","match-resource");
					ruleElem.setAttribute("value","exact");
					ruleElem.setAttribute("action","error");

					DataEvent *dataEvent = new DataEvent(AFlush);
					QCoreApplication::postEvent(this, dataEvent);

					sent = FStanzaProcessor->sendStanzaOut(FStreamJid,paket);
				}
				else
				{
					paket.setType(STANZA_TYPE_SET);
					FDataIqRequestId = paket.id();
					sent = FStanzaProcessor->sendStanzaRequest(this,FStreamJid,paket,DATA_TIMEOUT);
				}
			}

			if (sent)
			{
				FSeqOut = FSeqOut<USHRT_MAX ? FSeqOut+1 : 0;
				emit bytesWritten(data.size());
				FBytesWrittenCondition.wakeAll();
			}
			else
			{
				abort(XmppError(IERR_INBAND_STREAM_DATA_NOT_SENT));
			}
		}
	}
	return sent;
}
void RegisterStream::onRegisterDialogRejected()
{
	LOG_STRM_INFO(FXmppStream->streamJid(),"Account registration terminated by user");
	FXmppStream->setKeepAliveTimerActive(true);
	emit error(XmppError(IERR_REGISTER_REJECTED_BY_USER));
	FDialog = NULL;
}
Exemple #5
0
void DataMediaWidget::onUrlLoaded(const QUrl &AUrl, const QByteArray &AData)
{
    if (FUriIndex<FMedia.uris.count() && FMedia.uris.at(FUriIndex).url == AUrl)
    {
        const IDataMediaURI &uri = FMedia.uris.at(FUriIndex);
        if (!updateWidget(uri, AData))
        {
            FUriIndex++;
            FLastError = XmppError(IERR_DATAFORMS_MEDIA_INVALID_FORMAT);
            loadUri();
        }
    }
}
Exemple #6
0
void Roster::stanzaRequestResult(const Jid &AStreamJid, const Stanza &AStanza)
{
	if (AStanza.id() == FDelimRequestId)
	{
		FDelimRequestId.clear();
		QString groupDelim = ROSTER_GROUP_DELIMITER;
		if (AStanza.type() == "result")
		{
			groupDelim = AStanza.firstElement("query",NS_JABBER_PRIVATE).firstChildElement("roster").text();
			if (groupDelim.isEmpty())
			{
				groupDelim = ROSTER_GROUP_DELIMITER;
				LOG_STRM_INFO(streamJid(),QString("Saving default roster group delimiter on server, delimiter='%1'").arg(groupDelim));

				Stanza delim("iq");
				delim.setType("set").setId(FStanzaProcessor->newId());
				QDomElement elem = delim.addElement("query",NS_JABBER_PRIVATE);
				elem.appendChild(delim.createElement("roster",NS_STORAGE_GROUP_DELIMITER)).appendChild(delim.createTextNode(groupDelim));
				FStanzaProcessor->sendStanzaOut(AStreamJid,delim);
			}
			else
			{
				LOG_STRM_INFO(streamJid(),QString("Roster group delimiter loaded, delimiter='%1'").arg(groupDelim));
			}
		}
		else
		{
			LOG_STRM_WARNING(streamJid(),QString("Failed to load roster group delimiter: %1").arg(XmppStanzaError(AStanza).condition()));
		}
		setGroupDelimiter(groupDelim);
		requestRosterItems();
	}
	else if (AStanza.id() == FOpenRequestId)
	{
		FOpenRequestId.clear();
		if (AStanza.type() == "result")
		{
			LOG_STRM_INFO(streamJid(),"Roster items loaded");
			processItemsElement(AStanza.firstElement("query",NS_JABBER_ROSTER),true);
			FOpened = true;
			emit opened();
		}
		else
		{
			LOG_STRM_WARNING(streamJid(),QString("Failed to load roster items: %1").arg(XmppStanzaError(AStanza).condition()));
			FXmppStream->abort(XmppError(IERR_ROSTER_REQUEST_FAILED));
		}
	}
}
Exemple #7
0
DataMediaWidget::DataMediaWidget(IDataForms *ADataForms, const IDataMedia &AMedia, QWidget *AParent) : QLabel(AParent)
{
    FMedia = AMedia;
    FDataForms = ADataForms;

    setTextFormat(Qt::PlainText);
    setFrameShape(QLabel::Panel);
    setFrameShadow(QLabel::Sunken);

    connect(FDataForms->instance(),SIGNAL(urlLoaded(const QUrl &, const QByteArray &)),SLOT(onUrlLoaded(const QUrl &, const QByteArray &)));
    connect(FDataForms->instance(),SIGNAL(urlLoadFailed(const QUrl &, const XmppError &)),SLOT(onUrlLoadFailed(const QUrl &, const XmppError &)));

    FUriIndex = 0;
    FLastError = XmppError(IERR_DATAFORMS_MEDIA_INVALID_TYPE);

    QTimer::singleShot(0,this,SLOT(loadUri()));
}
void RegisterStream::onRegisterDialogAccepred()
{
	FXmppStream->setKeepAliveTimerActive(true);
	if (FDialog)
	{
		Stanza submit("iq");
		submit.setType("set").setId("setReg");
		QDomElement query = submit.addElement("query",NS_JABBER_REGISTER);
		FDataForms->xmlForm(FDataForms->dataSubmit(FDialog->formWidget()->userDataForm()),query);
		FXmppStream->sendStanza(submit);

		LOG_STRM_INFO(FXmppStream->streamJid(),"Account registration submit request sent");
	}
	else
	{
		LOG_STRM_WARNING(FXmppStream->streamJid(),"Account registration form dialog destroyed");
		emit error(XmppError(IERR_REGISTER_INVALID_DIALOG));
	}
	FDialog = NULL;
}
Exemple #9
0
void InBandStream::stanzaRequestResult(const Jid &AStreamJid, const Stanza &AStanza)
{
	Q_UNUSED(AStreamJid);
	if (AStanza.id() == FDataIqRequestId)
	{
		if (AStanza.isResult())
		{
			FDataIqRequestId.clear();
			sendNextPaket();
		}
		else
		{
			abort(XmppStanzaError(AStanza));
		}
	}
	else if (AStanza.id() == FOpenRequestId)
	{
		if (AStanza.isResult())
		{
			FSHIData = insertStanzaHandle(FStanzaType==StanzaMessage ? SHC_INBAND_DATA_MESSAGE : SHC_INBAND_DATA_IQ);
			FSHIClose = insertStanzaHandle(SHC_INBAND_CLOSE);
			if (FSHIData>0 && FSHIClose>0)
				setStreamState(IDataStreamSocket::Opened);
			else
				abort(XmppError(IERR_INBAND_STREAM_NOT_OPENED));
		}
		else
		{
			abort(XmppStanzaError(AStanza));
		}
	}
	else if (AStanza.id() == FCloseRequestId)
	{
		setStreamState(IDataStreamSocket::Closed);
	}
}
Exemple #10
0
bool InBandStream::stanzaReadWrite(int AHandleId, const Jid &AStreamJid, Stanza &AStanza, bool &AAccept)
{
	QDomElement elem = AStanza.firstElement(QString::null,NS_INBAND_BYTESTREAMS);
	if (AHandleId==FSHIData && elem.attribute("sid")==FStreamId)
	{
		AAccept = true;
		if (AStanza.firstElement("error").isNull())
		{
			QByteArray data =  QByteArray::fromBase64(elem.text().toLatin1());
			if (FSeqIn==elem.attribute("seq").toInt() && data.size()>0 && data.size()<=FBlockSize)
			{
				if (AStanza.kind() == STANZA_KIND_IQ)
				{
					Stanza result = FStanzaProcessor->makeReplyResult(AStanza);
					FStanzaProcessor->sendStanzaOut(AStreamJid,result);
				}

				FThreadLock.lockForWrite();
				FReadBuffer.write(data);
				FThreadLock.unlock();

				FSeqIn = FSeqIn<USHRT_MAX ? FSeqIn+1 : 0;
				emit readyRead();
				FReadyReadCondition.wakeAll();
			}
			else
			{
				abort(XmppError(IERR_INBAND_STREAM_INVALID_DATA));
			}
		}
		else
		{
			abort(XmppStanzaError(AStanza));
		}
	}
	else if (AHandleId==FSHIOpen && elem.attribute("sid")==FStreamId)
	{
		AAccept = true;
		removeStanzaHandle(FSHIOpen);
		if (FStreamState == IDataStreamSocket::Opening)
		{
			QDomElement openElem = AStanza.firstElement("open");
			FBlockSize = openElem.attribute("block-size").toInt();
			if (FBlockSize>MINIMUM_BLOCK_SIZE && FBlockSize<=FMaxBlockSize)
			{
				FStanzaType = openElem.attribute("stanza")==STANZA_KIND_MESSAGE ? StanzaMessage : StanzaIq;
				FSHIData = insertStanzaHandle(FStanzaType==StanzaMessage ? SHC_INBAND_DATA_MESSAGE : SHC_INBAND_DATA_IQ);
				FSHIClose = insertStanzaHandle(SHC_INBAND_CLOSE);
				if (FSHIData>0 && FSHIClose>0)
				{
					Stanza result = FStanzaProcessor->makeReplyResult(AStanza);
					if (FStanzaProcessor->sendStanzaOut(AStreamJid,result))
						setStreamState(IDataStreamSocket::Opened);
					else
						abort(XmppError(IERR_INBAND_STREAM_NOT_OPENED));
				}
				else
				{
					Stanza error = FStanzaProcessor->makeReplyError(AStanza,XmppStanzaError::EC_INTERNAL_SERVER_ERROR);
					FStanzaProcessor->sendStanzaOut(AStreamJid,error);
					abort(XmppError(IERR_INBAND_STREAM_NOT_OPENED));
				}
			}
			else
			{
				Stanza error = FStanzaProcessor->makeReplyError(AStanza,XmppStanzaError::EC_RESOURCE_CONSTRAINT);
				FStanzaProcessor->sendStanzaOut(AStreamJid,error);
				abort(XmppError(IERR_INBAND_STREAM_INVALID_BLOCK_SIZE));
			}
		}
		else
		{
			LOG_STRM_WARNING(AStreamJid,QString("Unexpected open request from=%1, sid=%2: Invalid state").arg(AStanza.from(),FStreamId));
			Stanza error = FStanzaProcessor->makeReplyError(AStanza,XmppStanzaError::EC_UNEXPECTED_REQUEST);
			FStanzaProcessor->sendStanzaOut(AStreamJid,error);
		}
	}
	else if (AHandleId==FSHIClose && elem.attribute("sid")==FStreamId)
	{
		AAccept = true;
		Stanza result = FStanzaProcessor->makeReplyResult(AStanza);
		FStanzaProcessor->sendStanzaOut(AStreamJid,result);
		setStreamState(IDataStreamSocket::Closed);
	}
	return false;
}
Exemple #11
0
InBandStream::~InBandStream()
{
	abort(XmppError(IERR_INBAND_STREAM_DESTROYED));
	LOG_STRM_INFO(FStreamJid,QString("In-band stream destroyed, sid=%1, kind=%2").arg(FStreamId).arg(FStreamKind));
}
bool RegisterStream::xmppStanzaIn(IXmppStream *AXmppStream, Stanza &AStanza, int AOrder)
{
	if (AXmppStream==FXmppStream && AOrder==XSHO_XMPP_FEATURE)
	{
		if (AStanza.id() == "getReg")
		{
			if (AStanza.type() == "result")
			{
				LOG_STRM_INFO(AXmppStream->streamJid(),"Account registration fileds loaded");

				QDomElement queryElem = AStanza.firstElement("query",NS_JABBER_REGISTER);
				QDomElement formElem = Stanza::findElement(queryElem,"x",NS_JABBER_DATA);
				if (FDataForms && !formElem.isNull())
				{
					IDataForm form = FDataForms->dataForm(formElem);
					if (FDataForms->isFormValid(form))
					{
						int userFiled = FDataForms->fieldIndex("username",form.fields);
						if (userFiled >= 0)
						{
							form.fields[userFiled].value = FXmppStream->streamJid().node();
							form.fields[userFiled].type = DATAFIELD_TYPE_HIDDEN;
						}

						int passFiled = FDataForms->fieldIndex("password",form.fields);
						if (passFiled >= 0)
						{
							form.fields[passFiled].value = FXmppStream->getSessionPassword();
							form.fields[passFiled].type = DATAFIELD_TYPE_HIDDEN;
						}

						FDialog = FDataForms->dialogWidget(form,NULL);
						FDialog->setAllowInvalid(false);
						FDialog->instance()->setWindowTitle(tr("Registration on %1").arg(FXmppStream->streamJid().domain()));
						connect(FDialog->instance(),SIGNAL(accepted()),SLOT(onRegisterDialogAccepred()));
						connect(FDialog->instance(),SIGNAL(rejected()),SLOT(onRegisterDialogRejected()));
						WidgetManager::showActivateRaiseWindow(FDialog->instance());
						FXmppStream->setKeepAliveTimerActive(false);

						LOG_STRM_INFO(AXmppStream->streamJid(),"Account registration form dialog shown");
					}
					else
					{
						LOG_STRM_WARNING(AXmppStream->streamJid(),"Failed to register new account on server: Invalid registration form received");
						emit error(XmppError(IERR_REGISTER_INVALID_FORM));
					}
				}
				else
				{
					Stanza submit("iq");
					submit.setType("set").setId("setReg");
					QDomElement querySubmit = submit.addElement("query",NS_JABBER_REGISTER);
					if (!queryElem.firstChildElement("username").isNull())
						querySubmit.appendChild(submit.createElement("username")).appendChild(submit.createTextNode(FXmppStream->streamJid().node()));
					if (!queryElem.firstChildElement("password").isNull())
						querySubmit.appendChild(submit.createElement("password")).appendChild(submit.createTextNode(FXmppStream->getSessionPassword()));
					if (!queryElem.firstChildElement("key").isNull())
						querySubmit.appendChild(submit.createElement("key")).appendChild(submit.createTextNode(AStanza.firstElement("query").attribute("key")));
					FXmppStream->sendStanza(submit);

					LOG_STRM_INFO(AXmppStream->streamJid(),"Account registration submit request sent");
				}
			}
			else
			{
				XmppStanzaError err(AStanza);
				LOG_STRM_WARNING(AXmppStream->streamJid(),QString("Failed to load account registration fields: %1").arg(err.condition()));
				emit error(err);
			}
			return true;
		}
		else if (AStanza.id() == "setReg")
		{
			FXmppStream->removeXmppStanzaHandler(XSHO_XMPP_FEATURE,this);
			if (AStanza.type() == "result")
			{
				REPORT_EVENT(SEVP_REGISTRATION_STREAM_SUCCESS,1);
				LOG_STRM_INFO(AXmppStream->streamJid(),"Account registration submit accepted");
				deleteLater();
				emit finished(false);
			}
			else
			{
				XmppStanzaError err(AStanza);
				LOG_STRM_WARNING(AXmppStream->streamJid(),QString("Account registration submit rejected: %1").arg(err.condition()));
				emit error(err);
			}
			return true;
		}
	}
	return false;
}
Exemple #13
0
bool IqAuthFeature::xmppStanzaIn(IXmppStream *AXmppStream, Stanza &AStanza, int AOrder)
{
	if (AXmppStream==FXmppStream && AOrder==XSHO_XMPP_FEATURE)
	{
		if (AStanza.id() == "getIqAuth")
		{
			if (AStanza.type() == "result")
			{
				Stanza auth("iq");
				auth.setType("set").setTo(FXmppStream->streamJid().domain()).setId("setIqAuth");
				QDomElement query = auth.addElement("query",NS_JABBER_IQ_AUTH);
				query.appendChild(auth.createElement("username")).appendChild(auth.createTextNode(FXmppStream->streamJid().pNode()));
				query.appendChild(auth.createElement("resource")).appendChild(auth.createTextNode(FXmppStream->streamJid().resource()));

				QDomElement reqElem = AStanza.firstElement("query",NS_JABBER_IQ_AUTH);
				if (!reqElem.firstChildElement("digest").isNull())
				{
					QByteArray shaData = FXmppStream->streamId().toUtf8()+FXmppStream->password().toUtf8();
					QByteArray shaDigest = QCryptographicHash::hash(shaData,QCryptographicHash::Sha1).toHex();
					query.appendChild(auth.createElement("digest")).appendChild(auth.createTextNode(shaDigest.toLower().trimmed()));
					FXmppStream->sendStanza(auth);
					LOG_STRM_INFO(AXmppStream->streamJid(),"Username and encrypted password sent");
				}
				else if (!reqElem.firstChildElement("password").isNull())
				{
					if (FXmppStream->connection()->isEncrypted())
					{
						query.appendChild(auth.createElement("password")).appendChild(auth.createTextNode(FXmppStream->password()));
						FXmppStream->sendStanza(auth);
						LOG_STRM_INFO(AXmppStream->streamJid(),"Username and plain text password sent");
					}
					else
					{
						LOG_STRM_ERROR(AXmppStream->streamJid(),"Failed to send username and plain text password: Connection not encrypted");
						emit error(XmppError(IERR_XMPPSTREAM_NOT_SECURE));
					}
				}
			}
			else
			{
				XmppStanzaError err(AStanza);
				LOG_STRM_ERROR(AXmppStream->streamJid(),QString("Failed to receive authentication initialization: %1").arg(err.condition()));
				emit error(err);
			}
			return true;
		}
		else if (AStanza.id() == "setIqAuth")
		{
			FXmppStream->removeXmppStanzaHandler(XSHO_XMPP_FEATURE,this);
			if (AStanza.type() == "result")
			{
				LOG_STRM_INFO(AXmppStream->streamJid(),"Username and password accepted");
				deleteLater();
				emit finished(false);
			}
			else
			{
				XmppStanzaError err(AStanza);
				LOG_STRM_WARNING(AXmppStream->streamJid(),QString("Username and password rejected: %1").arg(err.condition()));
				emit error(XmppStanzaError(AStanza));
			}
			return true;
		}
	}
	return false;
}