diff options
author | Remko Tronçon <git@el-tramo.be> | 2010-10-17 12:13:36 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2010-10-21 18:25:00 (GMT) |
commit | 1b58ef2af54456004390a0888c3edf104e3baa99 (patch) | |
tree | dbe4ae29de1b765a88ea704dfaa1c03af4b196b3 /Swiften/Serializer/PayloadSerializers | |
parent | 07402c4e3451f2084a1c3ddc5bacfb38a66899a7 (diff) | |
download | swift-contrib-1b58ef2af54456004390a0888c3edf104e3baa99.zip swift-contrib-1b58ef2af54456004390a0888c3edf104e3baa99.tar.bz2 |
Added beginnings of outgoing file transfer to Swiften.
Diffstat (limited to 'Swiften/Serializer/PayloadSerializers')
10 files changed, 312 insertions, 3 deletions
diff --git a/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp new file mode 100644 index 0000000..9acabee --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h" + +#include <boost/shared_ptr.hpp> +#include <boost/lexical_cast.hpp> + +#include "Swiften/Base/foreach.h" +#include "Swiften/Serializer/XML/XMLElement.h" +#include "Swiften/Serializer/PayloadSerializerCollection.h" + + +namespace Swift { + +BytestreamsSerializer::BytestreamsSerializer() { +} + +String BytestreamsSerializer::serializePayload(boost::shared_ptr<Bytestreams> bytestreams) const { + XMLElement queryElement("query", "http://jabber.org/protocol/bytestreams"); + queryElement.setAttribute("sid", bytestreams->getStreamID()); + foreach(const Bytestreams::StreamHost& streamHost, bytestreams->getStreamHosts()) { + boost::shared_ptr<XMLElement> streamHostElement(new XMLElement("streamhost")); + streamHostElement->setAttribute("host", streamHost.host); + streamHostElement->setAttribute("jid", streamHost.jid.toString()); + streamHostElement->setAttribute("port", boost::lexical_cast<std::string>(streamHost.port)); + queryElement.addNode(streamHostElement); + } + + if (bytestreams->getUsedStreamHost()) { + boost::shared_ptr<XMLElement> streamHostElement(new XMLElement("streamhost-used")); + streamHostElement->setAttribute("jid", *bytestreams->getUsedStreamHost()); + queryElement.addNode(streamHostElement); + } + return queryElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h new file mode 100644 index 0000000..50d58c2 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/BytestreamsSerializer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include "Swiften/Serializer/GenericPayloadSerializer.h" +#include "Swiften/Elements/Bytestreams.h" + +namespace Swift { + class PayloadSerializerCollection; + + class BytestreamsSerializer : public GenericPayloadSerializer<Bytestreams> { + public: + BytestreamsSerializer(); + + virtual String serializePayload(boost::shared_ptr<Bytestreams>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp index ece8fd8..77c2fd4 100644 --- a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp @@ -145,7 +145,9 @@ boost::shared_ptr<XMLElement> FormSerializer::fieldToXML(boost::shared_ptr<FormF foreach (const FormField::Option& option, field->getOptions()) { boost::shared_ptr<XMLElement> optionElement(new XMLElement("option")); - optionElement->setAttribute("label", option.label); + if (!option.label.isEmpty()) { + optionElement->setAttribute("label", option.label); + } boost::shared_ptr<XMLElement> valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(option.value)); diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index 8598f17..1d04456 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -7,6 +7,7 @@ #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" #include "Swiften/Base/foreach.h" #include "Swiften/Serializer/PayloadSerializer.h" +#include "Swiften/Serializer/PayloadSerializers/IBBSerializer.h" #include "Swiften/Serializer/PayloadSerializers/BodySerializer.h" #include "Swiften/Serializer/PayloadSerializers/SubjectSerializer.h" #include "Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h" @@ -26,6 +27,8 @@ #include "Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h" #include "Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h" #include "Swiften/Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.h" +#include "Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h" +#include "Swiften/Serializer/PayloadSerializers/ByteStreamsSerializer.h" #include "Swiften/Serializer/PayloadSerializers/VCardSerializer.h" #include "Swiften/Serializer/PayloadSerializers/VCardUpdateSerializer.h" #include "Swiften/Serializer/PayloadSerializers/RawXMLPayloadSerializer.h" @@ -39,6 +42,7 @@ namespace Swift { FullPayloadSerializerCollection::FullPayloadSerializerCollection() { + serializers_.push_back(new IBBSerializer()); serializers_.push_back(new BodySerializer()); serializers_.push_back(new SubjectSerializer()); serializers_.push_back(new ChatStateSerializer()); @@ -58,6 +62,8 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() { serializers_.push_back(new StartSessionSerializer()); serializers_.push_back(new SecurityLabelSerializer()); serializers_.push_back(new SecurityLabelsCatalogSerializer()); + serializers_.push_back(new StreamInitiationSerializer()); + serializers_.push_back(new BytestreamsSerializer()); serializers_.push_back(new VCardSerializer()); serializers_.push_back(new VCardUpdateSerializer()); serializers_.push_back(new RawXMLPayloadSerializer()); diff --git a/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp b/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp new file mode 100644 index 0000000..5e52145 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/IBBSerializer.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Serializer/PayloadSerializers/IBBSerializer.h" + +#include <boost/shared_ptr.hpp> +#include <boost/lexical_cast.hpp> + +#include "Swiften/Base/foreach.h" +#include "Swiften/Serializer/XML/XMLElement.h" +#include "Swiften/Serializer/XML/XMLTextNode.h" +#include "Swiften/Serializer/PayloadSerializerCollection.h" +#include "Swiften/StringCodecs/Base64.h" + +namespace Swift { + +IBBSerializer::IBBSerializer() { +} + +String IBBSerializer::serializePayload(boost::shared_ptr<IBB> ibb) const { + switch(ibb->getAction()) { + case IBB::Data: { + XMLElement ibbElement("data", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb->getStreamID()); + if (ibb->getSequenceNumber() >= 0) { + ibbElement.setAttribute("seq", boost::lexical_cast<std::string>(ibb->getSequenceNumber())); + } + ibbElement.addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(Base64::encode(ibb->getData())))); + return ibbElement.serialize(); + } + case IBB::Open: { + XMLElement ibbElement("open", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb->getStreamID()); + switch (ibb->getStanzaType()) { + case IBB::IQStanza: ibbElement.setAttribute("stanza", "iq"); break; + case IBB::MessageStanza: ibbElement.setAttribute("stanza", "message"); break; + } + assert(ibb->getBlockSize() > 0); + ibbElement.setAttribute("block-size", boost::lexical_cast<std::string>(ibb->getBlockSize())); + return ibbElement.serialize(); + } + case IBB::Close: { + XMLElement ibbElement("close", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb->getStreamID()); + return ibbElement.serialize(); + } + } + return ""; +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/IBBSerializer.h b/Swiften/Serializer/PayloadSerializers/IBBSerializer.h new file mode 100644 index 0000000..71b1c80 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/IBBSerializer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include "Swiften/Serializer/GenericPayloadSerializer.h" +#include "Swiften/Elements/IBB.h" + +namespace Swift { + class PayloadSerializerCollection; + + class IBBSerializer : public GenericPayloadSerializer<IBB> { + public: + IBBSerializer(); + + virtual String serializePayload(boost::shared_ptr<IBB>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp new file mode 100644 index 0000000..71702d0 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h" + +#include <boost/shared_ptr.hpp> +#include <boost/lexical_cast.hpp> + +#include "Swiften/Base/foreach.h" +#include "Swiften/Serializer/XML/XMLElement.h" +#include "Swiften/Serializer/XML/XMLTextNode.h" +#include "Swiften/Serializer/XML/XMLRawTextNode.h" +#include "Swiften/Serializer/PayloadSerializerCollection.h" +#include "Swiften/Serializer/PayloadSerializers/FormSerializer.h" + + +#define FILE_TRANSFER_NS "http://jabber.org/protocol/si/profile/file-transfer" +#define FEATURE_NEG_NS "http://jabber.org/protocol/feature-neg" + +namespace Swift { + +StreamInitiationSerializer::StreamInitiationSerializer() { +} + +String StreamInitiationSerializer::serializePayload(boost::shared_ptr<StreamInitiation> streamInitiation) const { + assert(streamInitiation->getIsFileTransfer()); + + XMLElement siElement("si", "http://jabber.org/protocol/si"); + if (!streamInitiation->getID().isEmpty()) { + siElement.setAttribute("id", streamInitiation->getID()); + } + siElement.setAttribute("profile", FILE_TRANSFER_NS); + + if (streamInitiation->getFileInfo()) { + StreamInitiation::FileInfo file = *streamInitiation->getFileInfo(); + boost::shared_ptr<XMLElement> fileElement(new XMLElement("file", "http://jabber.org/protocol/si/profile/file-transfer")); + fileElement->setAttribute("name", file.name); + if (file.size != -1) { + fileElement->setAttribute("size", boost::lexical_cast<std::string>(file.size)); + } + if (!file.description.isEmpty()) { + boost::shared_ptr<XMLElement> descElement(new XMLElement("desc")); + descElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(file.description))); + fileElement->addNode(descElement); + } + siElement.addNode(fileElement); + } + + boost::shared_ptr<XMLElement> featureElement(new XMLElement("feature", "http://jabber.org/protocol/feature-neg")); + if (streamInitiation->getProvidedMethods().size() > 0) { + Form::ref form(new Form(Form::FormType)); + ListSingleFormField::ref field = ListSingleFormField::create(); + field->setName("stream-method"); + foreach(const String& method, streamInitiation->getProvidedMethods()) { + field->addOption(FormField::Option("", method)); + } + form->addField(field); + featureElement->addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(FormSerializer().serialize(form)))); + } + else if (!streamInitiation->getRequestedMethod().isEmpty()) { + Form::ref form(new Form(Form::SubmitType)); + ListSingleFormField::ref field = ListSingleFormField::create(streamInitiation->getRequestedMethod()); + field->setName("stream-method"); + form->addField(field); + featureElement->addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(FormSerializer().serialize(form)))); + } + siElement.addNode(featureElement); + return siElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h new file mode 100644 index 0000000..35c71b9 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include "Swiften/Serializer/GenericPayloadSerializer.h" +#include "Swiften/Elements/StreamInitiation.h" + +namespace Swift { + class PayloadSerializerCollection; + + class StreamInitiationSerializer : public GenericPayloadSerializer<StreamInitiation> { + public: + StreamInitiationSerializer(); + + virtual String serializePayload(boost::shared_ptr<StreamInitiation>) const; + }; +} diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp index ebc8664..4ed3ba9 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/FormSerializerTest.cpp @@ -84,7 +84,7 @@ class FormSerializerTest : public CppUnit::TestFixture { field->addOption(FormField::Option("30", "30")); field->addOption(FormField::Option("50", "50")); field->addOption(FormField::Option("100", "100")); - field->addOption(FormField::Option("None", "none")); + field->addOption(FormField::Option("", "none")); form->addField(field); std::vector<JID> jids; @@ -132,7 +132,7 @@ class FormSerializerTest : public CppUnit::TestFixture { "<option label=\"30\"><value>30</value></option>" "<option label=\"50\"><value>50</value></option>" "<option label=\"100\"><value>100</value></option>" - "<option label=\"None\"><value>none</value></option>" + "<option><value>none</value></option>" "</field>" "<field label=\"People to invite\" type=\"jid-multi\" var=\"invitelist\">" "<desc>Tell all your friends about your new bot!</desc>" diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp new file mode 100644 index 0000000..12c8485 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.h" + +using namespace Swift; + +class StreamInitiationSerializerTest : public CppUnit::TestFixture{ + CPPUNIT_TEST_SUITE(StreamInitiationSerializerTest); + CPPUNIT_TEST(testSerialize_Request); + CPPUNIT_TEST(testSerialize_Response); + CPPUNIT_TEST_SUITE_END(); + + public: + void testSerialize_Request() { + StreamInitiationSerializer testling; + boost::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); + StreamInitiation::FileInfo fileInfo("test.txt", "This is info about the file.", 1022); + streamInitiation->setID("a0"); + streamInitiation->setFileInfo(fileInfo); + streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams"); + streamInitiation->addProvidedMethod("jabber:iq:oob"); + streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb"); + + CPPUNIT_ASSERT_EQUAL(String( + "<si id=\"a0\" profile=\"http://jabber.org/protocol/si/profile/file-transfer\" xmlns=\"http://jabber.org/protocol/si\">" + "<file name=\"test.txt\" size=\"1022\" xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" + "<desc>This is info about the file.</desc>" + "</file>" + "<feature xmlns=\"http://jabber.org/protocol/feature-neg\">" + "<x type=\"form\" xmlns=\"jabber:x:data\">" + "<field type=\"list-single\" var=\"stream-method\">" + "<option><value>http://jabber.org/protocol/bytestreams</value></option>" + "<option><value>jabber:iq:oob</value></option>" + "<option><value>http://jabber.org/protocol/ibb</value></option>" + "</field>" + "</x>" + "</feature>" + "</si>" + ), testling.serialize(streamInitiation)); + } + + void testSerialize_Response() { + StreamInitiationSerializer testling; + boost::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation()); + streamInitiation->setRequestedMethod("http://jabber.org/protocol/bytestreams"); + + CPPUNIT_ASSERT_EQUAL(String( + "<si profile=\"http://jabber.org/protocol/si/profile/file-transfer\" xmlns=\"http://jabber.org/protocol/si\">" + "<feature xmlns=\"http://jabber.org/protocol/feature-neg\">" + "<x type=\"submit\" xmlns=\"jabber:x:data\">" + "<field type=\"list-single\" var=\"stream-method\">" + "<value>http://jabber.org/protocol/bytestreams</value>" + "</field>" + "</x>" + "</feature>" + "</si>" + ), testling.serialize(streamInitiation)); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(StreamInitiationSerializerTest); |