[xdata] Safe the raw character data of form field values

This commit is contained in:
Florian Schmaus 2021-07-18 17:21:50 +02:00
parent 4643d07ef4
commit 097d245358
9 changed files with 121 additions and 31 deletions

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2020 Florian Schmaus
* Copyright 2015-2021 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -82,4 +82,11 @@ public class CollectionUtil {
}
return new HashSet<>(collection);
}
public static <T> List<T> emptyOrSingletonListFrom(T element) {
if (element == null) {
return Collections.emptyList();
}
return Collections.singletonList(element);
}
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2020 Florian Schmaus
* Copyright 2020-2021 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,9 +29,12 @@ public class AbstractMultiFormField extends FormField {
private final List<String> values;
private final List<String> rawValues;
protected AbstractMultiFormField(Builder<?, ?> builder) {
super(builder);
values = CollectionUtil.cloneAndSeal(builder.values);
rawValues = CollectionUtil.cloneAndSeal(builder.rawValues);
}
@Override
@ -39,11 +42,16 @@ public class AbstractMultiFormField extends FormField {
return values;
}
@Override
public final List<String> getRawValues() {
return rawValues;
}
public abstract static class Builder<F extends FormField, B extends FormField.Builder<F, B>>
public abstract static class Builder<F extends AbstractMultiFormField, B extends FormField.Builder<F, B>>
extends FormField.Builder<F, B> {
private List<String> values;
private List<String> rawValues;
protected Builder(AbstractMultiFormField formField) {
super(formField);
@ -57,6 +65,7 @@ public class AbstractMultiFormField extends FormField {
private void ensureValuesAreInitialized() {
if (values == null) {
values = new ArrayList<>();
rawValues = new ArrayList<>();
}
}
@ -70,7 +79,9 @@ public class AbstractMultiFormField extends FormField {
public B addValueVerbatim(CharSequence value) {
ensureValuesAreInitialized();
values.add(value.toString());
String valueString = value.toString();
values.add(valueString);
rawValues.add(valueString);
return getThis();
}
@ -83,7 +94,7 @@ public class AbstractMultiFormField extends FormField {
ensureValuesAreInitialized();
for (CharSequence value : values) {
this.values.add(value.toString());
addValueVerbatim(value);
}
return getThis();

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2020 Florian Schmaus.
* Copyright 2020-2021 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -42,7 +42,8 @@ public class AbstractSingleStringValueFormField extends SingleValueFormField {
return Integer.valueOf(value);
}
public abstract static class Builder<F extends FormField, B extends FormField.Builder<F, B>> extends FormField.Builder<F, B> {
public abstract static class Builder<F extends SingleValueFormField, B extends SingleValueFormField.Builder<F, B>>
extends SingleValueFormField.Builder<F, B> {
private String value;
@ -74,18 +75,16 @@ public class AbstractSingleStringValueFormField extends SingleValueFormField {
}
public B setValue(CharSequence value) {
this.value = value.toString();
this.rawValue = this.value = value.toString();
return getThis();
}
public B setValue(Enum<?> value) {
this.value = value.toString();
return getThis();
return setValue(value.toString());
}
public B setValue(int value) {
this.value = Integer.toString(value);
return getThis();
return setValue(Integer.toString(value));
}
public B setValue(URL value) {

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2020 Florian Schmaus.
* Copyright 2020-2021 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -43,7 +43,7 @@ public class BooleanFormField extends SingleValueFormField {
return new Builder(this);
}
public static final class Builder extends FormField.Builder<BooleanFormField, BooleanFormField.Builder> {
public static final class Builder extends SingleValueFormField.Builder<BooleanFormField, BooleanFormField.Builder> {
private Boolean value;
private Builder(BooleanFormField booleanFormField) {
@ -57,6 +57,7 @@ public class BooleanFormField extends SingleValueFormField {
@Override
protected void resetInternal() {
super.resetInternal();
value = null;
}
@ -74,11 +75,13 @@ public class BooleanFormField extends SingleValueFormField {
}
public Builder setValue(CharSequence value) {
boolean valueBoolean = ParserUtils.parseXmlBoolean(value.toString());
rawValue = value.toString();
boolean valueBoolean = ParserUtils.parseXmlBoolean(rawValue);
return setValue(valueBoolean);
}
public Builder setValue(boolean value) {
rawValue = Boolean.toString(value);
this.value = value;
return this;
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2003-2007 Jive Software, 2019-2020 Florian Schmaus.
* Copyright 2003-2007 Jive Software, 2019-2021 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -271,6 +271,8 @@ public abstract class FormField implements FullyQualifiedElement {
*/
public abstract List<? extends CharSequence> getValues();
public abstract List<String> getRawValues();
public boolean hasValueSet() {
List<?> values = getValues();
return !values.isEmpty();

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2020 Florian Schmaus.
* Copyright 2020-2021 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,14 +23,18 @@ import java.util.List;
import org.jivesoftware.smack.util.CollectionUtil;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.util.JidUtil;
public class JidMultiFormField extends FormField {
public final class JidMultiFormField extends FormField {
private final List<Jid> values;
private final List<String> rawValues;
protected JidMultiFormField(Builder builder) {
super(builder);
values = CollectionUtil.cloneAndSeal(builder.values);
rawValues = CollectionUtil.cloneAndSeal(builder.rawValues);
}
@Override
@ -38,6 +42,11 @@ public class JidMultiFormField extends FormField {
return values;
}
@Override
public List<String> getRawValues() {
return rawValues;
}
public Builder asBuilder() {
return new Builder(this);
}
@ -45,6 +54,8 @@ public class JidMultiFormField extends FormField {
public static final class Builder extends FormField.Builder<JidMultiFormField, JidMultiFormField.Builder> {
private List<Jid> values;
private List<String> rawValues;
private Builder(JidMultiFormField jidMultiFormField) {
super(jidMultiFormField);
values = CollectionUtil.newListWith(jidMultiFormField.getValues());
@ -57,18 +68,30 @@ public class JidMultiFormField extends FormField {
private void ensureValuesAreInitialized() {
if (values == null) {
values = new ArrayList<>();
rawValues = new ArrayList<>();
}
}
@Override
protected void resetInternal() {
values = null;
rawValues = null;
}
public Builder addValue(Jid jid) {
return addValue(jid, null);
}
public Builder addValue(Jid jid, String rawValue) {
if (rawValue == null) {
rawValue = jid.toString();
}
ensureValuesAreInitialized();
values.add(jid);
rawValues.add(rawValue);
return this;
}
@ -76,6 +99,7 @@ public class JidMultiFormField extends FormField {
ensureValuesAreInitialized();
values.addAll(jids);
rawValues.addAll(JidUtil.toStringList(jids));
return this;
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2020 Florian Schmaus.
* Copyright 2020-2021 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,7 +36,7 @@ public class JidSingleFormField extends SingleValueFormField {
return new Builder(this);
}
public static final class Builder extends FormField.Builder<JidSingleFormField, JidSingleFormField.Builder> {
public static final class Builder extends SingleValueFormField.Builder<JidSingleFormField, JidSingleFormField.Builder> {
private Jid value;
private Builder(JidSingleFormField jidSingleFormField) {
@ -50,11 +50,21 @@ public class JidSingleFormField extends SingleValueFormField {
@Override
protected void resetInternal() {
super.resetInternal();
value = null;
}
public Builder setValue(Jid value) {
return setValue(value, null);
}
public Builder setValue(Jid value, String rawValue) {
this.value = value;
if (rawValue != null) {
this.rawValue = rawValue;
} else {
this.rawValue = value.toString();
}
return this;
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright 2020 Florian Schmaus.
* Copyright 2020-2021 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,23 +19,35 @@ package org.jivesoftware.smackx.xdata;
import java.util.Collections;
import java.util.List;
import org.jivesoftware.smack.util.CollectionUtil;
public abstract class SingleValueFormField extends FormField {
private final String rawValue;
protected SingleValueFormField(Builder<?, ?> builder) {
super(builder);
rawValue = builder.rawValue;
}
@Override
public final List<CharSequence> getValues() {
CharSequence value = getValue();
if (value == null) {
return Collections.emptyList();
}
return Collections.singletonList(value);
return CollectionUtil.emptyOrSingletonListFrom(value);
}
public abstract CharSequence getValue();
public final String getRawValue() {
return rawValue;
}
@Override
public final List<String> getRawValues() {
String rawValue = getRawValue();
return CollectionUtil.emptyOrSingletonListFrom(rawValue);
}
@Override
protected void populateExtraXmlChildElements() {
CharSequence value = getValue();
@ -45,4 +57,24 @@ public abstract class SingleValueFormField extends FormField {
extraXmlChildElements = Collections.singletonList(new Value(value));
}
public abstract static class Builder<F extends SingleValueFormField, B extends Builder<F, B>>
extends FormField.Builder<F, B> {
protected Builder(String fieldName, Type type) {
super(fieldName, type);
}
protected Builder(FormField formField) {
super(formField);
}
protected String rawValue;
@Override
protected void resetInternal() {
rawValue = null;
};
}
}

View File

@ -237,8 +237,9 @@ public class DataFormProvider extends ExtensionElementProvider<DataForm> {
case jid_multi:
JidMultiFormField.Builder jidMultiBuilder = FormField.jidMultiBuilder(fieldName);
for (FormField.Value value : values) {
Jid jid = JidCreate.from(value.getValue());
jidMultiBuilder.addValue(jid);
String rawValue = value.getValue().toString();
Jid jid = JidCreate.from(rawValue);
jidMultiBuilder.addValue(jid, rawValue);
}
builder = jidMultiBuilder;
break;
@ -246,9 +247,9 @@ public class DataFormProvider extends ExtensionElementProvider<DataForm> {
ensureAtMostSingleValue(type, values);
JidSingleFormField.Builder jidSingleBuilder = FormField.jidSingleBuilder(fieldName);
if (!values.isEmpty()) {
CharSequence jidCharSequence = values.get(0).getValue();
Jid jid = JidCreate.from(jidCharSequence);
jidSingleBuilder.setValue(jid);
String rawValue = values.get(0).getValue().toString();
Jid jid = JidCreate.from(rawValue);
jidSingleBuilder.setValue(jid, rawValue);
}
builder = jidSingleBuilder;
break;
@ -322,7 +323,8 @@ public class DataFormProvider extends ExtensionElementProvider<DataForm> {
private static AbstractMultiFormField.Builder<?, ?> parseMultiKindFormField(AbstractMultiFormField.Builder<?, ?> builder,
List<FormField.Value> values) {
for (FormField.Value value : values) {
builder.addValue(value.getValue());
String rawValue = value.getValue().toString();
builder.addValue(rawValue);
}
return builder;
}