/** * Copyright (c) 2013, Redsolution LTD. All rights reserved. * * This file is part of Xabber project; you can redistribute it and/or * modify it under the terms of the GNU General Public License, Version 3. * * Xabber 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, see http://www.gnu.org/licenses/. */ package com.xabber.xmpp.ssn; import com.xabber.xmpp.PacketExtension; import com.xabber.xmpp.ProviderUtils; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.packet.DataForm; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.NoSuchElementException; /** * Packet extension for Stanza Session Negotiation. * <p/> * http://xmpp.org/extensions/xep-0155.html * * @author alexander.ivanov */ public class Feature extends PacketExtension { private static final String NAMESPACE = "http://jabber.org/protocol/feature-neg"; private static final String ELEMENT_NAME = "feature"; public static final String FORM_TYPE_FIELD = "FORM_TYPE"; public static final String FORM_TYPE_VALUE = "urn:xmpp:ssn"; private static final String ACCEPT_FIELD = "accept"; private static final String RENEGOTIATE_FIELD = "renegotiate"; private static final String TERMINATE_FIELD = "terminate"; public static final String LOGGING_FIELD = "logging"; private static final String DISCLOSURE_FIELD = "disclosure"; private static final String SECURITY_FIELD = "security"; private DataForm dataForm; public Feature() { } public Feature(DataForm dataForm) { this(); setDataForm(dataForm); } @Override public void serializeContent(XmlSerializer serializer) throws IOException { } @Override public boolean isValid() { if (dataForm == null) return false; DataForm.Type dataFormType = getDataFormType(); if (dataFormType == null || dataFormType == DataForm.Type.cancel) return false; int selected = 0; if (getAcceptValue() != null) selected += 1; if (getRenegotiateValue() != null) selected += 1; if (getTerminateValue() != null) { if (!getTerminateValue() || dataFormType != DataForm.Type.submit) return false; selected += 1; } if (selected != 1) return false; return FORM_TYPE_VALUE.equals(getValue(FORM_TYPE_FIELD)); } @Override public String getElementName() { return ELEMENT_NAME; } @Override public String getNamespace() { return NAMESPACE; } public DataForm getDataForm() { return dataForm; } public void setDataForm(DataForm dataForm) { this.dataForm = dataForm; } static public DataForm createDataForm(DataForm.Type type) { DataForm dataForm = new DataForm(type); FormField typeField = new FormField(FORM_TYPE_FIELD); typeField.addValue(FORM_TYPE_VALUE); typeField.setType(FormField.Type.hidden); dataForm.addField(typeField); return dataForm; } static private void addRequiredBooleanField(DataForm dataForm, String name, String label, boolean value) { FormField field = new FormField(name); field.setRequired(true); field.setLabel(label); field.addValue(Boolean.valueOf(value).toString()); field.setType(FormField.Type.bool); dataForm.addField(field); } static public void addAcceptField(DataForm dataForm, boolean value) { addRequiredBooleanField(dataForm, ACCEPT_FIELD, "Accept this session?", value); } static public void addRenegotiateField(DataForm dataForm, boolean value) { addRequiredBooleanField(dataForm, RENEGOTIATE_FIELD, "Renegotiate?", value); } static public void addTerminateField(DataForm dataForm) { addRequiredBooleanField(dataForm, TERMINATE_FIELD, null, true); } static public void addLoggingField(DataForm dataForm, LoggingValue[] options, LoggingValue value) { FormField field = new FormField(LOGGING_FIELD); field.setRequired(true); field.setLabel("Message logging"); field.setType(FormField.Type.list_single); if (options != null) for (LoggingValue loggingValue : options) field.addOption(loggingValue.createOption()); field.addValue(value.name()); dataForm.addField(field); } public static void addDisclosureField(DataForm dataForm, DisclosureValue[] options, DisclosureValue value) { FormField field = new FormField(DISCLOSURE_FIELD); field.setRequired(false); field.setLabel("Disclosure of content, decryption keys or identities"); field.setType(FormField.Type.list_single); if (options != null) for (DisclosureValue loggingValue : options) field.addOption(loggingValue.createOption()); field.addValue(value.name()); dataForm.addField(field); } public static void addSecurityField(DataForm dataForm, SecurityValue[] options, SecurityValue value) { FormField field = new FormField(SECURITY_FIELD); field.setRequired(false); field.setLabel("Minimum security level"); field.setType(FormField.Type.list_single); if (options != null) for (SecurityValue loggingValue : options) field.addOption(loggingValue.createOption()); field.addValue(value.name()); dataForm.addField(field); } private FormField getField(String name) { for (FormField field : dataForm.getFields()) { if (name.equals(field.getVariable())) return field; } return null; } public Collection<LoggingValue> getLoggingOptions() { FormField field = getField(LOGGING_FIELD); if (field == null) { return null; } Collection<LoggingValue> collection = new ArrayList<>(); List<FormField.Option> options = field.getOptions(); for (FormField.Option option : options) { collection.add(LoggingValue.fromString(option.getValue())); } return collection; } public Collection<DisclosureValue> getDisclosureOptions() { FormField field = getField(DISCLOSURE_FIELD); if (field == null) { return null; } Collection<DisclosureValue> collection = new ArrayList<>(); List<FormField.Option> options = field.getOptions(); for (FormField.Option option : options) { collection.add(DisclosureValue.fromString(option.getValue())); } return collection; } public Collection<SecurityValue> getSecurityOptions() { FormField field = getField(SECURITY_FIELD); if (field == null) { return null; } Collection<SecurityValue> collection = new ArrayList<>(); List<FormField.Option> options = field.getOptions(); for (FormField.Option option : options) { collection.add(SecurityValue.fromString(option.getValue())); } return collection; } private String getValue(String name) { FormField field = getField(name); if (field == null) return null; List<String> values = field.getValues(); if (!values.isEmpty()) { return null; } return values.get(0); } public LoggingValue getLoggingValue() { String value = getValue(LOGGING_FIELD); try { return LoggingValue.fromString(value); } catch (NoSuchElementException e) { return null; } } public Boolean getAcceptValue() { return ProviderUtils.parseBoolean(getValue(ACCEPT_FIELD)); } public Boolean getRenegotiateValue() { return ProviderUtils.parseBoolean(getValue(RENEGOTIATE_FIELD)); } public Boolean getTerminateValue() { return ProviderUtils.parseBoolean(getValue(TERMINATE_FIELD)); } public DataForm.Type getDataFormType() { try { return dataForm.getType(); } catch (NoSuchElementException e) { return null; } } }