/* * Copyright (c) 2010 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Swiften/Serializer/PayloadSerializers/FormSerializer.h" #include #include #include "Swiften/Base/foreach.h" #include "Swiften/Base/String.h" #include "Swiften/Serializer/XML/XMLTextNode.h" #include "Swiften/Serializer/XML/XMLRawTextNode.h" using namespace Swift; namespace { template void serializeValueAsString(boost::shared_ptr field, boost::shared_ptr parent) { String value = boost::dynamic_pointer_cast(field)->getValue(); if (!value.isEmpty()) { boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(value)); parent->addNode(valueElement); } } } namespace Swift { FormSerializer::FormSerializer() : GenericPayloadSerializer
() { } String FormSerializer::serializePayload(boost::shared_ptr form) const { boost::shared_ptr formElement(new XMLElement("x", "jabber:x:data")); String type; switch (form->getType()) { case Form::FormType: type = "form"; break; case Form::SubmitType: type = "submit"; break; case Form::CancelType: type = "cancel"; break; case Form::ResultType: type = "result"; break; } formElement->setAttribute("type", type); if (!form->getTitle().isEmpty()) { multiLineify(form->getTitle(), "title", formElement); } if (!form->getInstructions().isEmpty()) { multiLineify(form->getInstructions(), "instructions", formElement); } foreach(boost::shared_ptr field, form->getFields()) { formElement->addNode(fieldToXML(field)); } return formElement->serialize(); } boost::shared_ptr FormSerializer::fieldToXML(boost::shared_ptr field) const { boost::shared_ptr fieldElement(new XMLElement("field")); if (!field->getName().isEmpty()) { fieldElement->setAttribute("var", field->getName()); } if (!field->getLabel().isEmpty()) { fieldElement->setAttribute("label", field->getLabel()); } if (field->getRequired()) { fieldElement->addNode(boost::shared_ptr(new XMLElement("required"))); } if (!field->getDescription().isEmpty()) { boost::shared_ptr descriptionElement(new XMLElement("desc")); descriptionElement->addNode(boost::shared_ptr(new XMLTextNode(field->getDescription()))); fieldElement->addNode(descriptionElement); } // Set the value and type String fieldType; if (boost::dynamic_pointer_cast(field)) { fieldType = "boolean"; boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(boost::dynamic_pointer_cast(field)->getValue() ? "1" : "0")); fieldElement->addNode(valueElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "fixed"; serializeValueAsString(field, fieldElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "hidden"; serializeValueAsString(field, fieldElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "list-single"; serializeValueAsString(field, fieldElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "text-private"; serializeValueAsString(field, fieldElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "text-single"; serializeValueAsString(field, fieldElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "jid-multi"; std::vector jids = boost::dynamic_pointer_cast(field)->getValue(); foreach(const JID& jid, jids) { boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(jid.toString())); fieldElement->addNode(valueElement); } } else if (boost::dynamic_pointer_cast(field)) { fieldType = "jid-single"; boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(boost::dynamic_pointer_cast(field)->getValue().toString())); fieldElement->addNode(valueElement); } else if (boost::dynamic_pointer_cast(field)) { fieldType = "list-multi"; std::vector lines = boost::dynamic_pointer_cast(field)->getValue(); foreach(const String& line, lines) { boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(line)); fieldElement->addNode(valueElement); } } else if (boost::dynamic_pointer_cast(field)) { fieldType = "text-multi"; multiLineify(boost::dynamic_pointer_cast(field)->getValue(), "value", fieldElement); } else if (boost::dynamic_pointer_cast(field)) { std::vector lines = boost::dynamic_pointer_cast(field)->getValue(); foreach(const String& line, lines) { boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(line)); fieldElement->addNode(valueElement); } } else { assert(false); } if (!fieldType.isEmpty()) { fieldElement->setAttribute("type", fieldType); } foreach (const FormField::Option& option, field->getOptions()) { boost::shared_ptr optionElement(new XMLElement("option")); if (!option.label.isEmpty()) { optionElement->setAttribute("label", option.label); } boost::shared_ptr valueElement(new XMLElement("value")); valueElement->addNode(XMLTextNode::create(option.value)); optionElement->addNode(valueElement); fieldElement->addNode(optionElement); } return fieldElement; } void FormSerializer::multiLineify(const String& text, const String& elementName, boost::shared_ptr element) const { String unRdText(text); unRdText.removeAll('\r'); std::vector lines = unRdText.split('\n'); foreach (String line, lines) { boost::shared_ptr lineElement(new XMLElement(elementName)); lineElement->addNode(boost::shared_ptr(new XMLTextNode(line))); element->addNode(lineElement); } } }