From d04f7e19a7f6b35784cd43a18a5134df21256fe9 2015-11-12 18:19:53 From: Jan Kaluza Date: 2015-11-12 18:19:53 Subject: [PATCH] Add FormUtils methods to make XMPP Forms handling easier to read even when keeping it portable between swiften2 and swiften3. --- diff --git a/include/transport/formutils.h b/include/transport/formutils.h new file mode 100644 index 0000000000000000000000000000000000000000..2af0a702bf5b67b396aedb8d9359b87bbaa30beb --- /dev/null +++ b/include/transport/formutils.h @@ -0,0 +1,45 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2015, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include "Swiften/Queries/Responder.h" +#include "Swiften/Elements/InBandRegistrationPayload.h" +#include "Swiften/Elements/RosterPayload.h" +#include +#include +#define HAVE_SWIFTEN_3 (SWIFTEN_VERSION >= 0x030000) + +namespace Transport { +namespace FormUtils { + + void addHiddenField(Swift::Form::ref form, const std::string &name, const std::string &value); + void addTextSingleField(Swift::Form::ref form, const std::string &name, const std::string &value, + const std::string &label, bool required = false); + void addTextPrivateField(Swift::Form::ref form, const std::string &name, const std::string &label, + bool required = false); + void addListSingleField(Swift::Form::ref form, const std::string &name, Swift::FormField::Option value, + const std::string &label, const std::string &def, bool required = false); + void addBooleanField(Swift::Form::ref form, const std::string &name, const std::string &value, + const std::string &label, bool required = false); + + std::string fieldValue(Swift::Form::ref, const std::string &key, const std::string &def); +} +} \ No newline at end of file diff --git a/include/transport/userregistration.h b/include/transport/userregistration.h index 8ce3c9d64e9dc38b86c6e2b4e94ad551d88523ac..e6e614b9304741e4d540025ef178b07a74c14fdc 100644 --- a/include/transport/userregistration.h +++ b/include/transport/userregistration.h @@ -76,6 +76,8 @@ class UserRegistration : public Swift::Responder payload, Swift::ErrorPayload::ref error, const UserInfo &row); void handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error, const std::string &barejid); + boost::shared_ptr generateInBandRegistrationPayload(const Swift::JID& from); + Swift::Form::ref generateRegistrationForm(const UserInfo &res, bool registered); Component *m_component; StorageBackend *m_storageBackend; diff --git a/src/formutils.cpp b/src/formutils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adef0eefbac744e7ccca8a407c71c8c6416ddd57 --- /dev/null +++ b/src/formutils.cpp @@ -0,0 +1,135 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2015, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/formutils.h" + +#if HAVE_SWIFTEN_3 +#include +#endif + +using namespace Swift; + +namespace Transport { +namespace FormUtils { + +void addHiddenField(Form::ref form, const std::string &name, const std::string &value) { +#if HAVE_SWIFTEN_3 + FormField::ref field = boost::make_shared(FormField::HiddenType, value); +#else + HiddenFormField::ref field = HiddenFormField::create(); + field->setValue(value); +#endif + field->setName(name); + form->addField(field); +} + +void addTextSingleField(Swift::Form::ref form, const std::string &name, const std::string &value, const std::string &label, bool required) { +#if HAVE_SWIFTEN_3 + FormField::ref field = boost::make_shared(FormField::TextSingleType, value); +#else + TextSingleFormField::ref field = TextSingleFormField::create(); + field->setValue(value); +#endif + field->setName(name); + field->setLabel(label); + field->setRequired(required); + form->addField(field); +} + +void addTextPrivateField(Swift::Form::ref form, const std::string &name, const std::string &label, bool required) { +#if HAVE_SWIFTEN_3 + FormField::ref field = boost::make_shared(FormField::TextPrivateType); +#else + TextPrivateFormField::ref field = TextPrivateFormField::create(); +#endif + field->setName(name); + field->setLabel(label); + field->setRequired(required); + form->addField(field); +} + +void addListSingleField(Swift::Form::ref form, const std::string &name, Swift::FormField::Option value, const std::string &label, const std::string &def, bool required) { +#if HAVE_SWIFTEN_3 + FormField::ref field = boost::make_shared(FormField::ListSingleType); +#else + ListSingleFormField::ref field = ListSingleFormField::create(); +#endif + field->setName(name); + field->setLabel(label); + field->addOption(value); +#if HAVE_SWIFTEN_3 + field->addValue(def); +#else + field->setValue(def); +#endif + form->addField(field); +} + + +void addBooleanField(Swift::Form::ref form, const std::string &name, const std::string &value, const std::string &label, bool required) { +#if HAVE_SWIFTEN_3 + FormField::ref field = boost::make_shared(FormField::BooleanType, value); +#else + BooleanFormField::ref field = BooleanFormField::create(); + field->setValue(value == "0"); +#endif + field->setName(name); + field->setLabel(label); + field->setRequired(required); + form->addField(field); +} + +std::string fieldValue(Swift::Form::ref form, const std::string &key, const std::string &def) { + const std::vector fields = form->getFields(); + for (std::vector::const_iterator it = fields.begin(); it != fields.end(); it++) { +#if HAVE_SWIFTEN_3 + FormField::ref field = *it; + if (field->getName() == key) { + return field->getValues()[0]; + } +#else + TextSingleFormField::ref textSingle = boost::dynamic_pointer_cast(*it); + if (textSingle && textSingle->getName() == key) { + return textSingle->getValue(); + } + + TextPrivateFormField::ref textPrivate = boost::dynamic_pointer_cast(*it); + if (textPrivate && textPrivate->getName() == key) { + return textPrivate->getValue(); + } + + ListSingleFormField::ref listSingle = boost::dynamic_pointer_cast(*it); + if (listSingle && listSingle->getName() == key) { + return listSingle->getValue(); + } + + BooleanFormField::ref boolean = boost::dynamic_pointer_cast(*it); + if (boolean && boolean->getName() == key) { + return boolen->getValue() ? "1" : "0"; + } +#endif + } + + return def; +} + + +} +} diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 90d4074b885ac21b2d471ff1bd4e36292d3b5c0d..ad467755910f15f68648e5ee4d5d19058c89a244 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -25,6 +25,7 @@ #include "transport/rostermanager.h" #include "transport/user.h" #include "transport/logging.h" +#include "transport/formutils.h" #include "Swiften/Elements/ErrorPayload.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include "Swiften/Network/BoostNetworkFactories.h" @@ -43,7 +44,9 @@ namespace Transport { DEFINE_LOGGER(logger, "UserRegistration"); -UserRegistration::UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder(component->m_iqRouter) { +UserRegistration::UserRegistration(Component *component, UserManager *userManager, + StorageBackend *storageBackend) +: Swift::Responder(component->m_iqRouter) { m_component = component; m_config = m_component->m_config; m_storageBackend = storageBackend; @@ -54,16 +57,18 @@ UserRegistration::~UserRegistration(){ } bool UserRegistration::registerUser(const UserInfo &row) { - UserInfo user; - bool registered = m_storageBackend->getUser(row.jid, user); - // This user is already registered - if (registered) + UserInfo dummy; + bool registered = m_storageBackend->getUser(row.jid, dummy); + + // This user is already registered, nothing to do + if (registered) { return false; + } m_storageBackend->setUser(row); - //same as in unregisterUser but here we have to pass UserInfo to handleRegisterRRResponse - AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(),row.jid)); + // Check if the server supports remoteroster XEP by sending request for the registered user's roster. + AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), row.jid)); request->onResponse.connect(boost::bind(&UserRegistration::handleRegisterRemoteRosterResponse, this, _1, _2, row)); request->send(); @@ -73,13 +78,15 @@ bool UserRegistration::registerUser(const UserInfo &row) { bool UserRegistration::unregisterUser(const std::string &barejid) { UserInfo userInfo; bool registered = m_storageBackend->getUser(barejid, userInfo); - // This user is not registered - if (!registered) + + // This user is not registered, nothing to do + if (!registered) { return false; + } onUserUnregistered(userInfo); - // We have to check if server supports remoteroster XEP and use it if it's supported or fallback to unsubscribe otherwise + // Check if the server supports remoteroster XEP by sending request for the registered user's roster. AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), barejid)); request->onResponse.connect(boost::bind(&UserRegistration::handleUnregisterRemoteRosterResponse, this, _1, _2, barejid)); request->send(); @@ -87,15 +94,17 @@ bool UserRegistration::unregisterUser(const std::string &barejid) { return true; } -void UserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported /*error*/, const UserInfo &row){ +void UserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const UserInfo &row){ if (remoteRosterNotSupported || !payload) { + // Remote roster is not support, so send normal Subscribe presence to add transport. Swift::Presence::ref response = Swift::Presence::create(); response->setFrom(m_component->getJID()); response->setTo(Swift::JID(row.jid)); response->setType(Swift::Presence::Subscribe); m_component->getStanzaChannel()->sendPresence(response); } - else{ + else { + // Remote roster is support, so use remoteroster XEP to add transport. Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); Swift::RosterItemPayload item; item.setJID(m_component->getJID()); @@ -104,8 +113,10 @@ void UserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptrgetIQRouter()); request->send(); } + onUserRegistered(row); + // If the JID for registration notification is configured, send the notification message. std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid"); BOOST_FOREACH(const std::string ¬ify_jid, x) { boost::shared_ptr msg(new Swift::Message()); @@ -116,15 +127,17 @@ void UserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported /*error*/, const std::string &barejid) { +void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const std::string &barejid) { UserInfo userInfo; bool registered = m_storageBackend->getUser(barejid, userInfo); - // This user is not registered + // This user is not registered, nothing do to if (!registered) return; if (remoteRosterNotSupported || !payload) { - std::list roster; + // Remote roster is ont support, so get the buddies from database + // and send Unsubsribe and Unsubscribed presence to them. + std::list roster; m_storageBackend->getBuddies(userInfo.id, roster); for(std::list::iterator u = roster.begin(); u != roster.end() ; u++){ std::string name = (*u).legacyName; @@ -152,6 +165,8 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptrgetItems()) { Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload()); Swift::RosterItemPayload item; @@ -174,6 +189,7 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptrremoveUser(user); } + // Remove the transport contact itself the same way as the buddies. if (remoteRosterNotSupported || !payload) { Swift::Presence::ref response; response = Swift::Presence::create(); @@ -199,6 +215,7 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptrsend(); } + // If the JID for registration notification is configured, send the notification message. std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid"); BOOST_FOREACH(const std::string ¬ify_jid, x) { boost::shared_ptr msg(new Swift::Message()); @@ -209,142 +226,75 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr payload) { - // TODO: backend should say itself if registration is needed or not... - if (CONFIG_STRING(m_config, "service.protocol") == "irc") { - sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); - return true; +Form::ref UserRegistration::generateRegistrationForm(const UserInfo &res, bool registered) { + Form::ref form(new Form(Form::FormType)); + form->setTitle("Registration"); + form->setInstructions(CONFIG_STRING(m_config, "registration.instructions")); + + FormUtils::addHiddenField(form, "FORM_TYPE", "jabber:iq:register"); + FormUtils::addTextSingleField(form, "username", res.uin, + CONFIG_STRING(m_config, "registration.username_label"), + true); + + if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { + FormUtils::addTextPrivateField(form, "password", "Password", true); } - std::string barejid = from.toBare().toString(); + std::string defLanguage = CONFIG_STRING(m_config, "registration.language"); + Swift::FormField::Option languages(defLanguage, defLanguage); + FormUtils::addListSingleField(form, "language", languages, "Language", + registered ? res.language : defLanguage); - if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { - std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); - if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { - LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") - sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); - return true; - } + + if (registered) { + FormUtils::addBooleanField(form, "unregister", "0", "Remove your registration"); + } + else if (CONFIG_BOOL(m_config,"registration.require_local_account")) { + std::string localUsernameField = CONFIG_STRING(m_config, "registration.local_username_label"); + FormUtils::addTextSingleField(form, "local_username", "", localUsernameField, true); + FormUtils::addTextSingleField(form, "local_password", "", "Local password", true); } + return form; +} + +boost::shared_ptr UserRegistration::generateInBandRegistrationPayload(const Swift::JID& from) { boost::shared_ptr reg(new InBandRegistrationPayload()); UserInfo res; - bool registered = m_storageBackend->getUser(barejid, res); + bool registered = m_storageBackend->getUser(from.toBare().toString(), res); - std::string instructions = CONFIG_STRING(m_config, "registration.instructions"); - std::string usernameField = CONFIG_STRING(m_config, "registration.username_label"); - - // normal jabber:iq:register - reg->setInstructions(instructions); + reg->setInstructions(CONFIG_STRING(m_config, "registration.instructions")); reg->setRegistered(registered); reg->setUsername(res.uin); + if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { reg->setPassword(""); } + Form::ref form = generateRegistrationForm(res, registered); + reg->setForm(form); - // form - Form::ref form(new Form(Form::FormType)); - form->setTitle((("Registration"))); - form->setInstructions((instructions)); -#if HAVE_SWIFTEN_3 - FormField::ref type = boost::make_shared(FormField::HiddenType, "jabber:iq:register"); -#else - HiddenFormField::ref type = HiddenFormField::create(); - type->setValue("jabber:iq:register"); -#endif - type->setName("FORM_TYPE"); - form->addField(type); -#if HAVE_SWIFTEN_3 - FormField::ref username = boost::make_shared(FormField::TextSingleType, res.uin); -#else - TextSingleFormField::ref username = TextSingleFormField::create(); - username->setValue(res.uin); -#endif - username->setName("username"); - username->setLabel((usernameField)); - username->setRequired(true); - form->addField(username); + return reg; +} - if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { -#if HAVE_SWIFTEN_3 - FormField::ref password = boost::make_shared(FormField::TextPrivateType); -#else - TextPrivateFormField::ref password = TextPrivateFormField::create(); -#endif - password->setName("password"); - password->setLabel((("Password"))); - password->setRequired(true); - form->addField(password); +bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + // TODO: backend should say itself if registration is needed or not... + if (CONFIG_STRING(m_config, "service.protocol") == "irc") { + sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); + return true; } -#if HAVE_SWIFTEN_3 - FormField::ref language = boost::make_shared(FormField::ListSingleType); -#else - ListSingleFormField::ref language = ListSingleFormField::create(); -#endif - language->setName("language"); - language->setLabel((("Language"))); - language->addOption(Swift::FormField::Option(CONFIG_STRING(m_config, "registration.language"), CONFIG_STRING(m_config, "registration.language"))); - if (registered) -#if HAVE_SWIFTEN_3 - language->addValue(res.language); -#else - language->setValue(res.language); -#endif - else -#if HAVE_SWIFTEN_3 - language->addValue(CONFIG_STRING(m_config, "registration.language")); -#else - language->setValue(CONFIG_STRING(m_config, "registration.language")); -#endif - form->addField(language); - -// TextSingleFormField::ref encoding = TextSingleFormField::create(); -// encoding->setName("encoding"); -// encoding->setLabel((("Encoding"))); -// if (registered) -// encoding->setValue(res.encoding); -// else -// encoding->setValue(CONFIG_STRING(m_config, "registration.encoding")); -// form->addField(encoding); - if (registered) { -#if HAVE_SWIFTEN_3 - FormField::ref boolean = boost::make_shared(FormField::BooleanType, "0"); -#else - BooleanFormField::ref boolean = BooleanFormField::create(); - boolean->setValue(0); -#endif - boolean->setName("unregister"); - boolean->setLabel((("Remove your registration"))); - form->addField(boolean); - } else { - if (CONFIG_BOOL(m_config,"registration.require_local_account")) { - std::string localUsernameField = CONFIG_STRING(m_config, "registration.local_username_label"); -#if HAVE_SWIFTEN_3 - FormField::ref local_username = boost::make_shared(FormField::TextSingleType); -#else - TextSingleFormField::ref local_username = TextSingleFormField::create(); -#endif - local_username->setName("local_username"); - local_username->setLabel((localUsernameField)); - local_username->setRequired(true); - form->addField(local_username); -#if HAVE_SWIFTEN_3 - FormField::ref local_password = boost::make_shared(FormField::TextPrivateType); -#else - TextPrivateFormField::ref local_password = TextPrivateFormField::create(); -#endif - local_password->setName("local_password"); - local_password->setLabel((("Local Password"))); - local_password->setRequired(true); - form->addField(local_password); + if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { + std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); + if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { + LOG4CXX_INFO(logger, from.toBare().toString() << ": This user has no permissions to register an account") + sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); + return true; } } - reg->setForm(form); - + boost::shared_ptr reg = generateInBandRegistrationPayload(from); sendResponse(from, id, reg); return true; @@ -373,127 +323,32 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID std::string encoding; std::string language; - std::string local_username(""); - std::string local_password(""); + std::string local_username; + std::string local_password; Form::ref form = payload->getForm(); if (form) { - const std::vector fields = form->getFields(); - for (std::vector::const_iterator it = fields.begin(); it != fields.end(); it++) { -#if HAVE_SWIFTEN_3 - FormField::ref textSingle = *it; - if (textSingle->getType() == FormField::TextSingleType || textSingle->getType() == FormField::UnknownType) { -#else - TextSingleFormField::ref textSingle = boost::dynamic_pointer_cast(*it); - if (textSingle) { -#endif - if (textSingle->getName() == "username") { -#if HAVE_SWIFTEN_3 - payload->setUsername(textSingle->getTextSingleValue()); -#else - payload->setUsername(textSingle->getValue()); -#endif - } - else if (textSingle->getName() == "encoding") { -#if HAVE_SWIFTEN_3 - encoding = textSingle->getTextSingleValue(); -#else - encoding = textSingle->getValue(); -#endif - } - // Pidgin sends it as textSingle, not sure why... - else if (textSingle->getName() == "password") { -#if HAVE_SWIFTEN_3 - payload->setPassword(textSingle->getTextSingleValue()); -#else - payload->setPassword(textSingle->getValue()); -#endif - } - else if (textSingle->getName() == "local_username") { -#if HAVE_SWIFTEN_3 - local_username = textSingle->getTextSingleValue(); -#else - local_username = textSingle->getValue(); -#endif - } - // Pidgin sends it as textSingle, not sure why... - else if (textSingle->getName() == "local_password") { -#if HAVE_SWIFTEN_3 - local_password = textSingle->getTextSingleValue(); -#else - local_password = textSingle->getValue(); -#endif - } - // Pidgin sends it as textSingle, not sure why... - else if (textSingle->getName() == "unregister") { -#if HAVE_SWIFTEN_3 - if (textSingle->getTextSingleValue() == "1" || textSingle->getTextSingleValue() == "true") { -#else - if (textSingle->getValue() == "1" || textSingle->getValue() == "true") { -#endif - payload->setRemove(true); - } - } - continue; - } -#if HAVE_SWIFTEN_3 - FormField::ref textPrivate = *it; - if (textPrivate->getType() == FormField::TextPrivateType) { -#else - TextPrivateFormField::ref textPrivate = boost::dynamic_pointer_cast(*it); - if (textPrivate) { -#endif - if (textPrivate->getName() == "password") { -#if HAVE_SWIFTEN_3 - payload->setPassword(textPrivate->getTextPrivateValue()); -#else - payload->setPassword(textPrivate->getValue()); -#endif - } - else if (textPrivate->getName() == "local_password") { -#if HAVE_SWIFTEN_3 - local_password = textPrivate->getTextPrivateValue(); -#else - local_password = textPrivate->getValue(); -#endif - } - continue; - } -#if HAVE_SWIFTEN_3 - FormField::ref listSingle = *it; - if (listSingle->getType() == FormField::ListSingleType) { -#else - ListSingleFormField::ref listSingle = boost::dynamic_pointer_cast(*it); - if (listSingle) { -#endif - if (listSingle->getName() == "language") { -#if HAVE_SWIFTEN_3 - language = listSingle->getValues()[0]; -#else - language = listSingle->getValue(); -#endif - } - continue; - } -#if HAVE_SWIFTEN_3 - FormField::ref boolean = *it; - if (boolean->getType() == FormField::BooleanType) { -#else - BooleanFormField::ref boolean = boost::dynamic_pointer_cast(*it); - if (boolean) { -#endif - if (boolean->getName() == "unregister") { -#if HAVE_SWIFTEN_3 - if (boolean->getBoolValue()) { -#else - if (boolean->getValue()) { -#endif - payload->setRemove(true); - } - } - continue; - } + std::string value; + + value = FormUtils::fieldValue(form, "username", ""); + if (!value.empty()) { + payload->setUsername(value); + } + + value = FormUtils::fieldValue(form, "password", ""); + if (!value.empty()) { + payload->setPassword(value); } + + value = FormUtils::fieldValue(form, "unregister", ""); + if (value == "1" || value == "true") { + payload->setRemove(true); + } + + encoding = FormUtils::fieldValue(form, "encoding", ""); + local_username = FormUtils::fieldValue(form, "local_username", ""); + local_password = FormUtils::fieldValue(form, "local_password", ""); + language = FormUtils::fieldValue(form, "language", ""); } if (payload->isRemove()) {