diff --git a/.gitignore b/.gitignore index f42f734..1dbae6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,2 @@ xstream-distribution-1.2.2-src.zip xstream-distribution-1.3.1-src.zip -/xstream-distribution-1.4.4-src.zip -/xstream-distribution-1.4.5-src.zip -/xstream-distribution-1.4.6-src.zip -/xstream-distribution-1.4.7-src.zip -/xstream-distribution-1.4.8-src.zip -/xstream-distribution-1.4.9-src.zip -/xstream-distribution-1.4.11.1-src.zip -/xstream-distribution-1.4.12-src.zip -/xstream-distribution-1.4.13-src.zip -/xstream-distribution-1.4.14-src.zip -/xstream-distribution-1.4.18-src.zip -/xstream-distribution-1.4.19-src.zip -/xstream-distribution-1.4.20-src.zip -/xstream-distribution-1.4.21-src.zip diff --git a/sources b/sources index 2df2f7c..6161bbc 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (xstream-distribution-1.4.21-src.zip) = 495a415bad652bd3ad3ea91f8e8e12a4cfa34c3ba87e8822e3686f545b8e5a38aceb93e854da4d52ab5a5388f50a586f44b03e4c6f884ead30304672afb08a55 +3a129d9bdf88e385424a917c59e284e2 xstream-distribution-1.3.1-src.zip diff --git a/xstream-CVE-2013-7285.patch b/xstream-CVE-2013-7285.patch new file mode 100644 index 0000000..cc56623 --- /dev/null +++ b/xstream-CVE-2013-7285.patch @@ -0,0 +1,1136 @@ +From b235f65141d07e5dc44b5965657bbe1e539cc966 Mon Sep 17 00:00:00 2001 +From: Mikolaj Izdebski +Date: Tue, 11 Feb 2014 10:44:19 +0100 +Subject: [PATCH] Fix for CVE-2013-7285 + +Backported from upstream revision 2210 +--- + xstream/build.xml | 2 +- + .../src/java/com/thoughtworks/xstream/XStream.java | 148 ++++++++++++++- + .../thoughtworks/xstream/core/util/Primitives.java | 4 + + .../thoughtworks/xstream/mapper/CachingMapper.java | 28 ++- + .../xstream/mapper/SecurityMapper.java | 75 ++++++++ + .../xstream/security/AnyTypePermission.java | 35 ++++ + .../xstream/security/ArrayTypePermission.java | 35 ++++ + .../xstream/security/ExplicitTypePermission.java | 38 ++++ + .../xstream/security/ForbiddenClassException.java | 27 +++ + .../xstream/security/NoPermission.java | 40 ++++ + .../xstream/security/NoTypePermission.java | 39 ++++ + .../xstream/security/NullPermission.java | 27 +++ + .../xstream/security/PrimitiveTypePermission.java | 37 ++++ + .../xstream/security/RegExpTypePermission.java | 49 +++++ + .../xstream/security/TypePermission.java | 25 +++ + .../xstream/security/WildcardTypePermission.java | 84 +++++++++ + .../xstream/mapper/SecurityMapperTest.java | 207 +++++++++++++++++++++ + 17 files changed, 890 insertions(+), 10 deletions(-) + create mode 100644 xstream/src/java/com/thoughtworks/xstream/mapper/SecurityMapper.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/AnyTypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/ArrayTypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/NoPermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/NoTypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/NullPermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/RegExpTypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/TypePermission.java + create mode 100644 xstream/src/java/com/thoughtworks/xstream/security/WildcardTypePermission.java + create mode 100644 xstream/src/test/com/thoughtworks/xstream/mapper/SecurityMapperTest.java + +diff --git a/xstream/build.xml b/xstream/build.xml +index 18ef35a..eaa187e 100644 +--- a/xstream/build.xml ++++ b/xstream/build.xml +@@ -62,7 +62,7 @@ + + + +- ++ + + + +diff --git a/xstream/src/java/com/thoughtworks/xstream/XStream.java b/xstream/src/java/com/thoughtworks/xstream/XStream.java +index 506e612..8af0f6a 100644 +--- a/xstream/src/java/com/thoughtworks/xstream/XStream.java ++++ b/xstream/src/java/com/thoughtworks/xstream/XStream.java +@@ -1,6 +1,6 @@ + /* + * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes. +- * Copyright (C) 2006, 2007, 2008 XStream Committers. ++ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 XStream Committers. + * All rights reserved. + * + * The software in this package is published under the terms of the BSD +@@ -92,8 +92,16 @@ import com.thoughtworks.xstream.mapper.Mapper; + import com.thoughtworks.xstream.mapper.MapperWrapper; + import com.thoughtworks.xstream.mapper.OuterClassMapper; + import com.thoughtworks.xstream.mapper.PackageAliasingMapper; ++import com.thoughtworks.xstream.mapper.SecurityMapper; + import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper; + import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper; ++import com.thoughtworks.xstream.security.AnyTypePermission; ++import com.thoughtworks.xstream.security.ExplicitTypePermission; ++import com.thoughtworks.xstream.security.NoPermission; ++import com.thoughtworks.xstream.security.NoTypePermission; ++import com.thoughtworks.xstream.security.RegExpTypePermission; ++import com.thoughtworks.xstream.security.TypePermission; ++import com.thoughtworks.xstream.security.WildcardTypePermission; + + import java.io.EOFException; + import java.io.File; +@@ -132,6 +140,7 @@ import java.util.Set; + import java.util.TreeMap; + import java.util.TreeSet; + import java.util.Vector; ++import java.util.regex.Pattern; + + + /** +@@ -256,7 +265,7 @@ import java.util.Vector; + * The XStream instance is thread-safe. That is, once the XStream instance has been created and + * configured, it may be shared across multiple threads allowing objects to be + * serialized/deserialized concurrently. Note, that this only applies if annotations are not +- * auto-detected on -the-fly. ++ * auto-detected on-the-fly. + *

+ *

Implicit collections

+ *

+@@ -292,6 +301,7 @@ public class XStream { + private ImmutableTypesMapper immutableTypesMapper; + private ImplicitCollectionMapper implicitCollectionMapper; + private LocalConversionMapper localConversionMapper; ++ private SecurityMapper securityMapper; + private AnnotationConfiguration annotationConfiguration; + + private transient JVM jvm = new JVM(); +@@ -440,6 +450,7 @@ public class XStream { + this.mapper = mapper == null ? buildMapper() : mapper; + + setupMappers(); ++ setupSecurity(); + setupAliases(); + setupDefaultImplementations(); + setupConverters(); +@@ -470,6 +481,7 @@ public class XStream { + } + mapper = new LocalConversionMapper(mapper); + mapper = new ImmutableTypesMapper(mapper); ++ mapper = new SecurityMapper(mapper); + if (JVM.is15()) { + mapper = buildMapperDynamically( + ANNOTATION_MAPPER_TYPE, +@@ -521,9 +533,19 @@ public class XStream { + .lookupMapperOfType(ImmutableTypesMapper.class); + localConversionMapper = (LocalConversionMapper)this.mapper + .lookupMapperOfType(LocalConversionMapper.class); ++ securityMapper = (SecurityMapper)this.mapper ++ .lookupMapperOfType(SecurityMapper.class); + annotationConfiguration = (AnnotationConfiguration)this.mapper + .lookupMapperOfType(AnnotationConfiguration.class); + } ++ ++ protected void setupSecurity() { ++ if (securityMapper == null) { ++ return; ++ } ++ ++ addPermission(AnyTypePermission.ANY); ++ } + + protected void setupAliases() { + if (classAliasingMapper == null) { +@@ -1620,4 +1642,126 @@ public class XStream { + return this; + } + ++ /** ++ * Add a new security permission. ++ * ++ *

++ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or ++ * {@link AnyTypePermission} will implicitly wipe any existing permission. ++ *

++ * ++ * @param permission the permission to add ++ * @since upcoming ++ */ ++ public void addPermission(TypePermission permission) { ++ if (securityMapper != null) { ++ securityMapper.addPermission(permission); ++ } ++ } ++ ++ /** ++ * Add security permission for explicit types by name. ++ * ++ * @param names the type names to allow ++ * @since upcoming ++ */ ++ public void allowTypes(String... names) { ++ addPermission(new ExplicitTypePermission(names)); ++ } ++ ++ /** ++ * Add security permission for types matching one of the specified regular expressions. ++ * ++ * @param regexps the regular expressions to allow type names ++ * @since upcoming ++ */ ++ public void allowTypesByRegExp(String... regexps) { ++ addPermission(new RegExpTypePermission(regexps)); ++ } ++ ++ /** ++ * Add security permission for types matching one of the specified regular expressions. ++ * ++ * @param regexps the regular expressions to allow type names ++ * @since upcoming ++ */ ++ public void allowTypesByRegExp(Pattern... regexps) { ++ addPermission(new RegExpTypePermission(regexps)); ++ } ++ ++ /** ++ * Add security permission for types matching one of the specified wildcard patterns. ++ *

++ * Supported are patterns with path expressions using dot as separator: ++ *

++ *
    ++ *
  • ?: one non-control character except separator, e.g. for 'java.net.Inet?Address'
  • ++ *
  • *: arbitrary number of non-control characters except separator, e.g. for types in a package like 'java.lang.*'
  • ++ *
  • **: arbitrary number of non-control characters including separator, e.g. for types in a package and subpackages like 'java.lang.**'
  • ++ *
++ * ++ * @param patterns the patterns to allow type names ++ * @since upcoming ++ */ ++ public void allowTypesByWildcard(String... patterns) { ++ addPermission(new WildcardTypePermission(patterns)); ++ } ++ ++ /** ++ * Add security permission denying another one. ++ * ++ * @param permission the permission to deny ++ * @since upcoming ++ */ ++ public void denyPermission(TypePermission permission) { ++ addPermission(new NoPermission(permission)); ++ } ++ ++ /** ++ * Add security permission forbidding explicit types by name. ++ * ++ * @param names the type names to forbid ++ * @since upcoming ++ */ ++ public void denyTypes(String... names) { ++ denyPermission(new ExplicitTypePermission(names)); ++ } ++ ++ /** ++ * Add security permission forbidding types matching one of the specified regular expressions. ++ * ++ * @param regexps the regular expressions to forbid type names ++ * @since upcoming ++ */ ++ public void denyTypesByRegExp(String... regexps) { ++ denyPermission(new RegExpTypePermission(regexps)); ++ } ++ ++ /** ++ * Add security permission forbidding types matching one of the specified regular expressions. ++ * ++ * @param regexps the regular expressions to forbid type names ++ * @since upcoming ++ */ ++ public void denyTypesByRegExp(Pattern... regexps) { ++ denyPermission(new RegExpTypePermission(regexps)); ++ } ++ ++ /** ++ * Add security permission forbidding types matching one of the specified wildcard patterns. ++ *

++ * Supported are patterns with path expressions using dot as separator: ++ *

++ *
    ++ *
  • ?: one non-control character except separator, e.g. for 'java.net.Inet?Address'
  • ++ *
  • *: arbitrary number of non-control characters except separator, e.g. for types in a package like 'java.lang.*'
  • ++ *
  • **: arbitrary number of non-control characters including separator, e.g. for types in a package and subpackages like 'java.lang.**'
  • ++ *
++ * ++ * @param patterns the patterns to forbid names ++ * @since upcoming ++ */ ++ public void denyTypesByWildcard(String... patterns) { ++ denyPermission(new WildcardTypePermission(patterns)); ++ } + } +diff --git a/xstream/src/java/com/thoughtworks/xstream/core/util/Primitives.java b/xstream/src/java/com/thoughtworks/xstream/core/util/Primitives.java +index f6e988e..e0f5fbf 100644 +--- a/xstream/src/java/com/thoughtworks/xstream/core/util/Primitives.java ++++ b/xstream/src/java/com/thoughtworks/xstream/core/util/Primitives.java +@@ -48,4 +48,8 @@ public final class Primitives { + static public Class unbox(final Class type) { + return (Class)UNBOX.get(type); + } ++ ++ static public boolean isBoxed(final Class type) { ++ return UNBOX.keySet().contains(type); ++ } + } +diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/CachingMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/CachingMapper.java +index 7e865c7..a90c194 100644 +--- a/xstream/src/java/com/thoughtworks/xstream/mapper/CachingMapper.java ++++ b/xstream/src/java/com/thoughtworks/xstream/mapper/CachingMapper.java +@@ -1,6 +1,6 @@ + /* + * Copyright (C) 2005 Joe Walnes. +- * Copyright (C) 2006, 2007, 2008 XStream Committers. ++ * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2014 XStream Committers. + * All rights reserved. + * + * The software in this package is published under the terms of the BSD +@@ -18,6 +18,9 @@ import java.util.Collections; + import java.util.HashMap; + import java.util.Map; + ++import com.thoughtworks.xstream.XStreamException; ++import com.thoughtworks.xstream.security.ForbiddenClassException; ++ + /** + * Mapper that caches which names map to which classes. Prevents repetitive searching and class loading. + * +@@ -43,15 +46,26 @@ public class CachingMapper extends MapperWrapper { + public Class realClass(String elementName) { + WeakReference reference = (WeakReference) realClassCache.get(elementName); + if (reference != null) { +- Class cached = (Class) reference.get(); ++ Object cached = reference.get(); + if (cached != null) { +- return cached; ++ if (cached instanceof Class) { ++ return (Class)cached; ++ } ++ throw (XStreamException)cached; + } + } +- +- Class result = super.realClass(elementName); +- realClassCache.put(elementName, new WeakReference(result)); +- return result; ++ ++ try { ++ Class result = super.realClass(elementName); ++ realClassCache.put(elementName, result); ++ return result; ++ } catch (ForbiddenClassException e) { ++ realClassCache.put(elementName, e); ++ throw e; ++ } catch (CannotResolveClassException e) { ++ realClassCache.put(elementName, e); ++ throw e; ++ } + } + + private Object readResolve() { +diff --git a/xstream/src/java/com/thoughtworks/xstream/mapper/SecurityMapper.java b/xstream/src/java/com/thoughtworks/xstream/mapper/SecurityMapper.java +new file mode 100644 +index 0000000..151bb91 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/mapper/SecurityMapper.java +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 08. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.mapper; ++ ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.List; ++ ++import com.thoughtworks.xstream.security.AnyTypePermission; ++import com.thoughtworks.xstream.security.ForbiddenClassException; ++import com.thoughtworks.xstream.security.NoTypePermission; ++import com.thoughtworks.xstream.security.TypePermission; ++ ++ ++/** ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class SecurityMapper extends MapperWrapper { ++ ++ private final List permissions; ++ ++ /** ++ * Construct a SecurityMapper. ++ * ++ * @param wrapped the mapper chain ++ * @since upcoming ++ */ ++ public SecurityMapper(final Mapper wrapped) { ++ this(wrapped, (TypePermission[])null); ++ } ++ ++ /** ++ * Construct a SecurityMapper. ++ * ++ * @param wrapped the mapper chain ++ * @param permissions the predefined permissions ++ * @since upcoming ++ */ ++ public SecurityMapper(final Mapper wrapped, final TypePermission... permissions) { ++ super(wrapped); ++ this.permissions = permissions == null // ++ ? new ArrayList() ++ : new ArrayList(Arrays.asList(permissions)); ++ } ++ ++ /** ++ * Add a new permission. ++ *

++ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or ++ * {@link AnyTypePermission} will implicitly wipe any existing permission. ++ *

++ * ++ * @param permission the permission to add. ++ * @since upcoming ++ */ ++ public void addPermission(final TypePermission permission) { ++ if (permission.equals(NoTypePermission.NONE) || permission.equals(AnyTypePermission.ANY)) ++ permissions.clear(); ++ permissions.add(permission); ++ } ++ ++ @Override ++ public Class realClass(final String elementName) { ++ final Class type = super.realClass(elementName); ++ for (final TypePermission permission : permissions) ++ if (permission.allows(type)) ++ return type; ++ throw new ForbiddenClassException(type); ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/AnyTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/AnyTypePermission.java +new file mode 100644 +index 0000000..a5ac1b6 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/AnyTypePermission.java +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 08. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++/** ++ * Permission for any type and null. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class AnyTypePermission implements TypePermission { ++ /** ++ * @since upcoming ++ */ ++ public static final TypePermission ANY = new AnyTypePermission(); ++ ++ @Override ++ public boolean allows(Class type) { ++ return true; ++ } ++ ++ @Override ++ public int hashCode() { ++ return 3; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ return obj != null && obj.getClass() == AnyTypePermission.class; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/ArrayTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/ArrayTypePermission.java +new file mode 100644 +index 0000000..0b425ef +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/ArrayTypePermission.java +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++/** ++ * Permission for any array type. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class ArrayTypePermission implements TypePermission { ++ /** ++ * @since upcoming ++ */ ++ public static final TypePermission ARRAYS = new ArrayTypePermission(); ++ ++ @Override ++ public boolean allows(Class type) { ++ return type != null && type.isArray(); ++ } ++ ++ @Override ++ public int hashCode() { ++ return 13; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ return obj != null && obj.getClass() == ArrayTypePermission.class; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java +new file mode 100644 +index 0000000..4294d72 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.Set; ++ ++/** ++ * Explicit permission for a type with a name matching one in the provided list. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class ExplicitTypePermission implements TypePermission { ++ ++ final Set names; ++ ++ /** ++ * @since upcoming ++ */ ++ public ExplicitTypePermission(String...names) { ++ this.names = names == null ? Collections.emptySet() : new HashSet(Arrays.asList(names)); ++ } ++ ++ @Override ++ public boolean allows(Class type) { ++ if (type == null) ++ return false; ++ return names.contains(type.getName()); ++ } ++ ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java b/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java +new file mode 100644 +index 0000000..041e47a +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/ForbiddenClassException.java +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 08. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++import com.thoughtworks.xstream.XStreamException; ++ ++/** ++ * Exception thrown for a forbidden class. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class ForbiddenClassException extends XStreamException { ++ ++ /** ++ * Construct a ForbiddenClassException. ++ * @param type the forbidden class ++ * @since upcoming ++ */ ++ public ForbiddenClassException(Class type) { ++ super(type == null ? "null" : type.getName()); ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/NoPermission.java b/xstream/src/java/com/thoughtworks/xstream/security/NoPermission.java +new file mode 100644 +index 0000000..4845112 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/NoPermission.java +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++/** ++ * Wrapper to negate another type permission. ++ *

++ * If the wrapped {@link TypePermission} allows the type, this instance will throw a {@link ForbiddenClassException} ++ * instead. An instance of this permission cannot be used to allow a type. ++ *

++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class NoPermission implements TypePermission { ++ ++ private final TypePermission permission; ++ ++ /** ++ * Construct a NoPermission. ++ * ++ * @param permission the permission to negate or null to forbid any type ++ * @since upcoming ++ */ ++ public NoPermission(final TypePermission permission) { ++ this.permission = permission; ++ } ++ ++ @Override ++ public boolean allows(final Class type) { ++ if (permission == null || permission.allows(type)) { ++ throw new ForbiddenClassException(type); ++ } ++ return false; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/NoTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/NoTypePermission.java +new file mode 100644 +index 0000000..bfaa7e7 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/NoTypePermission.java +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 08. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++/** ++ * No permission for any type. ++ *

++ * Can be used to skip any existing default permission. ++ *

++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class NoTypePermission implements TypePermission { ++ ++ /** ++ * @since upcoming ++ */ ++ public static final TypePermission NONE = new NoTypePermission(); ++ ++ @Override ++ public boolean allows(Class type) { ++ throw new ForbiddenClassException(type); ++ } ++ ++ @Override ++ public int hashCode() { ++ return 1; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ return obj != null && obj.getClass() == NoTypePermission.class; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/NullPermission.java b/xstream/src/java/com/thoughtworks/xstream/security/NullPermission.java +new file mode 100644 +index 0000000..a1b0372 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/NullPermission.java +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++import com.thoughtworks.xstream.mapper.Mapper; ++ ++/** ++ * Permission for null or XStream's null replacement type. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class NullPermission implements TypePermission { ++ /** ++ * @since upcoming ++ */ ++ public static final TypePermission NULL = new NullPermission(); ++ ++ @Override ++ public boolean allows(Class type) { ++ return type == null || type == Mapper.Null.class; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java +new file mode 100644 +index 0000000..58257c2 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++import com.thoughtworks.xstream.core.util.Primitives; ++ ++/** ++ * Permission for any primitive type and its boxed counterpart. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class PrimitiveTypePermission implements TypePermission { ++ /** ++ * @since upcoming ++ */ ++ public static final TypePermission PRIMITIVES = new PrimitiveTypePermission(); ++ ++ @Override ++ public boolean allows(Class type) { ++ return type != null && type.isPrimitive() || Primitives.isBoxed(type); ++ } ++ ++ @Override ++ public int hashCode() { ++ return 7; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ return obj != null && obj.getClass() == PrimitiveTypePermission.class; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/RegExpTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/RegExpTypePermission.java +new file mode 100644 +index 0000000..d5c8b57 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/RegExpTypePermission.java +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++import java.util.regex.Pattern; ++ ++ ++/** ++ * Permission for any type with a name matching one of the provided regular expressions. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class RegExpTypePermission implements TypePermission { ++ ++ private final Pattern[] patterns; ++ ++ public RegExpTypePermission(final String... patterns) { ++ this(getPatterns(patterns)); ++ } ++ ++ public RegExpTypePermission(final Pattern... patterns) { ++ this.patterns = patterns == null ? new Pattern[0] : patterns; ++ } ++ ++ @Override ++ public boolean allows(final Class type) { ++ if (type != null) { ++ final String name = type.getName(); ++ for (final Pattern pattern : patterns) ++ if (pattern.matcher(name).matches()) ++ return true; ++ } ++ return false; ++ } ++ ++ private static Pattern[] getPatterns(final String... patterns) { ++ if (patterns == null) ++ return null; ++ final Pattern[] array = new Pattern[patterns.length]; ++ for (int i = 0; i < array.length; ++i) ++ array[i] = Pattern.compile(patterns[i]); ++ return array; ++ } ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/TypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/TypePermission.java +new file mode 100644 +index 0000000..7246c22 +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/TypePermission.java +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 08. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++/** ++ * Definition of a type permission. ++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public interface TypePermission { ++ /** ++ * Check permission for a provided type. ++ * ++ * @param type the type to check ++ * @return true if provided type is allowed, false if permission does not handle the type ++ * @throws ForbiddenClassException if provided type is explicitly forbidden ++ * @since upcoming ++ */ ++ boolean allows(Class type); ++} +diff --git a/xstream/src/java/com/thoughtworks/xstream/security/WildcardTypePermission.java b/xstream/src/java/com/thoughtworks/xstream/security/WildcardTypePermission.java +new file mode 100644 +index 0000000..ffa93de +--- /dev/null ++++ b/xstream/src/java/com/thoughtworks/xstream/security/WildcardTypePermission.java +@@ -0,0 +1,84 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.security; ++ ++/** ++ * Permission for any type with a name matching one of the provided wildcard expressions. ++ * ++ *

++ * Supported are patterns with path expressions using dot as separator: ++ *

++ *
    ++ *
  • ?: one non-control character except separator, e.g. for 'java.net.Inet?Address'
  • ++ *
  • *: arbitrary number of non-control characters except separator, e.g. for types in a package like 'java.lang.*'
  • ++ *
  • **: arbitrary number of non-control characters including separator, e.g. for types in a package and subpackages like 'java.lang.**'
  • ++ *
++ *

++ * The complete range of UTF-8 characters is supported except control characters. ++ *

++ * ++ * @author Jörg Schaible ++ * @since upcoming ++ */ ++public class WildcardTypePermission extends RegExpTypePermission { ++ ++ /** ++ * @since upcoming ++ */ ++ public WildcardTypePermission(final String... patterns) { ++ super(getRegExpPatterns(patterns)); ++ } ++ ++ private static String[] getRegExpPatterns(final String... wildcards) { ++ if (wildcards == null) ++ return null; ++ final String[] regexps = new String[wildcards.length]; ++ for (int i = 0; i < wildcards.length; ++i) { ++ final String wildcardExpression = wildcards[i]; ++ final StringBuilder result = new StringBuilder(wildcardExpression.length() * 2); ++ result.append("(?u)"); ++ final int length = wildcardExpression.length(); ++ for (int j = 0; j < length; j++) { ++ final char ch = wildcardExpression.charAt(j); ++ switch (ch) { ++ case '\\': ++ case '.': ++ case '+': ++ case '|': ++ case '[': ++ case ']': ++ case '(': ++ case ')': ++ case '^': ++ case '$': ++ result.append('\\').append(ch); ++ break; ++ ++ case '?': ++ result.append('.'); ++ break; ++ ++ case '*': ++ // see "General Category Property" in http://www.unicode.org/reports/tr18/ ++ if (j + 1 < length && wildcardExpression.charAt(j + 1) == '*') { ++ result.append("[\\P{C}]*"); ++ j++; ++ } else { ++ result.append("[\\P{C}&&[^").append('.').append("]]*"); ++ } ++ break; ++ ++ default: ++ result.append(ch); ++ break; ++ } ++ } ++ regexps[i] = result.toString(); ++ } ++ return regexps; ++ } ++} +diff --git a/xstream/src/test/com/thoughtworks/xstream/mapper/SecurityMapperTest.java b/xstream/src/test/com/thoughtworks/xstream/mapper/SecurityMapperTest.java +new file mode 100644 +index 0000000..ebde756 +--- /dev/null ++++ b/xstream/src/test/com/thoughtworks/xstream/mapper/SecurityMapperTest.java +@@ -0,0 +1,207 @@ ++/* ++ * Copyright (C) 2014 XStream Committers. ++ * All rights reserved. ++ * ++ * Created on 09. January 2014 by Joerg Schaible ++ */ ++package com.thoughtworks.xstream.mapper; ++ ++import java.net.URL; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++ ++import com.thoughtworks.xstream.core.JVM; ++import com.thoughtworks.xstream.core.util.QuickWriter; ++import com.thoughtworks.xstream.security.AnyTypePermission; ++import com.thoughtworks.xstream.security.ArrayTypePermission; ++import com.thoughtworks.xstream.security.ExplicitTypePermission; ++import com.thoughtworks.xstream.security.ForbiddenClassException; ++import com.thoughtworks.xstream.security.NoTypePermission; ++import com.thoughtworks.xstream.security.NullPermission; ++import com.thoughtworks.xstream.security.PrimitiveTypePermission; ++import com.thoughtworks.xstream.security.RegExpTypePermission; ++import com.thoughtworks.xstream.security.TypePermission; ++import com.thoughtworks.xstream.security.WildcardTypePermission; ++ ++import junit.framework.TestCase; ++ ++ ++/** ++ * Tests the {@link SecurityMapper} and the {@link TypePermission} implementations. ++ * ++ * @author Jörg Schaible ++ */ ++public class SecurityMapperTest extends TestCase { ++ ++ private SecurityMapper mapper; ++ private Map> classMap; ++ ++ @Override ++ protected void setUp() throws Exception { ++ super.setUp(); ++ ++ classMap = new HashMap>(); ++ mapper = new SecurityMapper(new MapperWrapper(null) { ++ @Override ++ public Class realClass(final String elementName) { ++ return classMap.get(elementName); ++ } ++ }); ++ } ++ ++ private void register(final Class... types) { ++ for (final Class type : types) { ++ classMap.put(type.getName(), type); ++ } ++ } ++ ++ public void testAnyType() { ++ register(String.class, URL.class, List.class); ++ mapper.addPermission(NoTypePermission.NONE); ++ mapper.addPermission(AnyTypePermission.ANY); ++ assertSame(String.class, mapper.realClass(String.class.getName())); ++ assertSame(List.class, mapper.realClass(List.class.getName())); ++ assertNull(mapper.realClass(null)); ++ } ++ ++ public void testNoType() { ++ register(String.class, URL.class, List.class); ++ mapper.addPermission(NoTypePermission.NONE); ++ try { ++ mapper.realClass(String.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(String.class.getName(), e.getMessage()); ++ } ++ try { ++ mapper.realClass(null); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals("null", e.getMessage()); ++ } ++ } ++ ++ public void testNullType() { ++ register(String.class, Mapper.Null.class); ++ mapper.addPermission(NullPermission.NULL); ++ assertSame(Mapper.Null.class, mapper.realClass(Mapper.Null.class.getName())); ++ assertNull(mapper.realClass(null)); ++ try { ++ mapper.realClass(String.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(String.class.getName(), e.getMessage()); ++ } ++ } ++ ++ public void testPrimitiveTypes() { ++ register(String.class, int.class, Integer.class, char[].class, Character[].class); ++ mapper.addPermission(PrimitiveTypePermission.PRIMITIVES); ++ assertSame(int.class, mapper.realClass(int.class.getName())); ++ assertSame(Integer.class, mapper.realClass(Integer.class.getName())); ++ try { ++ mapper.realClass(String.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(String.class.getName(), e.getMessage()); ++ } ++ try { ++ mapper.realClass(null); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals("null", e.getMessage()); ++ } ++ try { ++ mapper.realClass(char[].class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(char[].class.getName(), e.getMessage()); ++ } ++ } ++ ++ public void testArrayTypes() { ++ register(String.class, int.class, Integer.class, char[].class, Character[].class); ++ mapper.addPermission(ArrayTypePermission.ARRAYS); ++ assertSame(char[].class, mapper.realClass(char[].class.getName())); ++ assertSame(Character[].class, mapper.realClass(Character[].class.getName())); ++ try { ++ mapper.realClass(String.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(String.class.getName(), e.getMessage()); ++ } ++ try { ++ mapper.realClass(null); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals("null", e.getMessage()); ++ } ++ try { ++ mapper.realClass(int.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(int.class.getName(), e.getMessage()); ++ } ++ } ++ ++ public void testExplicitTypes() { ++ register(String.class, List.class); ++ mapper.addPermission(new ExplicitTypePermission(String.class.getName(), List.class.getName())); ++ assertSame(String.class, mapper.realClass(String.class.getName())); ++ assertSame(List.class, mapper.realClass(List.class.getName())); ++ try { ++ mapper.realClass(null); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals("null", e.getMessage()); ++ } ++ } ++ ++ public void testNamesWithRegExps() { ++ class Foo$_0 {} ++ final Class anonymous = new Object() {}.getClass(); ++ register(String.class, JVM.class, QuickWriter.class, Foo$_0.class, anonymous, DefaultClassMapperTest.class); ++ mapper.addPermission(new RegExpTypePermission(".*Test", ".*\\.core\\..*", ".*SecurityMapperTest\\$.+")); ++ assertSame(DefaultClassMapperTest.class, mapper.realClass(DefaultClassMapperTest.class.getName())); ++ assertSame(JVM.class, mapper.realClass(JVM.class.getName())); ++ assertSame(QuickWriter.class, mapper.realClass(QuickWriter.class.getName())); ++ assertSame(Foo$_0.class, mapper.realClass(Foo$_0.class.getName())); ++ assertSame(anonymous, mapper.realClass(anonymous.getName())); ++ try { ++ mapper.realClass(String.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(String.class.getName(), e.getMessage()); ++ } ++ } ++ ++ public void testNamesWithWildcardPatterns() { ++ class Foo$_0 {} ++ class Foo$_1 {} ++ final Class anonymous = new Object() {}.getClass(); ++ register(String.class, JVM.class, QuickWriter.class, Foo$_0.class, Foo$_1.class, anonymous); ++ mapper.addPermission(new WildcardTypePermission("**.*_0", "**.core.*", "**.SecurityMapperTest$?")); ++ assertSame(JVM.class, mapper.realClass(JVM.class.getName())); ++ assertSame(Foo$_0.class, mapper.realClass(Foo$_0.class.getName())); ++ assertSame(anonymous, mapper.realClass(anonymous.getName())); ++ try { ++ mapper.realClass(String.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(String.class.getName(), e.getMessage()); ++ } ++ try { ++ mapper.realClass(QuickWriter.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(QuickWriter.class.getName(), e.getMessage()); ++ } ++ try { ++ mapper.realClass(Foo$_1.class.getName()); ++ fail("Thrown " + ForbiddenClassException.class.getName() + " expected"); ++ } catch (final ForbiddenClassException e) { ++ assertEquals(Foo$_1.class.getName(), e.getMessage()); ++ } ++ } ++} +-- +1.8.4.2 + diff --git a/xstream.spec b/xstream.spec index 9270386..975720c 100644 --- a/xstream.spec +++ b/xstream.spec @@ -1,413 +1,207 @@ -%bcond_without activation -%bcond_without cglib -%bcond_without dom4j -%bcond_without jdom -%bcond_without jdom2 -%bcond_with jettison -%bcond_with joda-time -%bcond_with kxml2 -%bcond_with stax -%bcond_with woodstox -%bcond_with xom -%bcond_with xpp3 +# Copyright statement from JPackage this file is derived from: + +# Copyright (c) 2000-2007, JPackage Project +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# 3. Neither the name of the JPackage Project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# Tests are disabled by default since we don't have +# all the requirements in Fedora yet +%bcond_with test Name: xstream -Version: 1.4.21 -Release: 2%{?dist} +Version: 1.3.1 +Release: 9%{?dist} Summary: Java XML serialization library -# Automatically converted from old format: BSD - review is highly recommended. -License: LicenseRef-Callaway-BSD -URL: https://x-stream.github.io + +Group: Development/Libraries +License: BSD +URL: http://xstream.codehaus.org/ +Source0: http://repository.codehaus.org/com/thoughtworks/%{name}/%{name}-distribution/%{version}/%{name}-distribution-%{version}-src.zip + +# Backported from upstream revision 2210 +Patch0: %{name}-CVE-2013-7285.patch + +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +BuildRequires: jpackage-utils >= 0:1.7.2 +BuildRequires: ant >= 0:1.6 +BuildRequires: bea-stax >= 0:1.2.0 +BuildRequires: bea-stax-api >= 0:1.0.1 +BuildRequires: cglib >= 0:2.1.3 +BuildRequires: dom4j >= 0:1.6.1 +BuildRequires: jakarta-commons-lang >= 0:2.1 +BuildRequires: jakarta-oro +BuildRequires: jdom >= 0:1.0 +BuildRequires: jettison >= 0:1.0 +BuildRequires: joda-time >= 0:1.2.1 +BuildRequires: junit >= 0:3.8.1 +BuildRequires: xom >= 0:1.0 +BuildRequires: xpp3 >= 0:1.1.3.4 +BuildRequires: unzip +BuildRequires: java-devel-openjdk +%if %with test +BuildRequires: jmock >= 0:1.0.1 +BuildRequires: wstx >= 0:3.2.0 +%endif +Requires: jpackage-utils +Requires: java +Requires: xpp3-minimal + BuildArch: noarch -ExclusiveArch: %{java_arches} noarch -Source0: https://repo1.maven.org/maven2/com/thoughtworks/%{name}/%{name}-distribution/%{version}/%{name}-distribution-%{version}-src.zip -BuildRequires: maven-local-openjdk25 -BuildRequires: mvn(io.github.x-stream:mxparser) -BuildRequires: mvn(jakarta.xml.bind:jakarta.xml.bind-api:2) -BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) -BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin) -BuildRequires: mvn(org.apache.maven.plugins:maven-enforcer-plugin) -BuildRequires: mvn(org.apache.maven.plugins:maven-source-plugin) -BuildRequires: mvn(org.codehaus.mojo:build-helper-maven-plugin) -%if %{with activation} -BuildRequires: mvn(jakarta.activation:jakarta.activation-api:1) -%endif -%if %{with cglib} -BuildRequires: mvn(cglib:cglib-nodep) -%endif -%if %{with dom4j} -BuildRequires: mvn(dom4j:dom4j) -%endif -%if %{with jdom} -BuildRequires: mvn(org.jdom:jdom) -%endif -%if %{with jdom2} -BuildRequires: mvn(org.jdom:jdom2) -%endif -%if %{with jettison} -BuildRequires: mvn(org.codehaus.jettison:jettison) -%endif -%if %{with joda-time} -BuildRequires: mvn(joda-time:joda-time) -%endif -%if %{with kxml2} -BuildRequires: mvn(net.sf.kxml:kxml2-min) -%endif -%if %{with stax} -BuildRequires: mvn(stax:stax) -BuildRequires: mvn(stax:stax-api) -%endif -%if %{with woodstox} -BuildRequires: mvn(org.codehaus.woodstox:wstx-asl) -%endif -%if %{with xom} -BuildRequires: mvn(xom:xom) -%endif -%if %{with xpp3} -BuildRequires: mvn(xpp3:xpp3_min) -%endif + %description -XStream is a simple library to serialize objects to XML -and back again. A high level facade is supplied that -simplifies common use cases. Custom objects can be serialized -without need for specifying mappings. Speed and low memory -footprint are a crucial part of the design, making it suitable -for large object graphs or systems with high message throughput. -No information is duplicated that can be obtained via reflection. -This results in XML that is easier to read for humans and more -compact than native Java serialization. XStream serializes internal -fields, including private and final. Supports non-public and inner -classes. Classes are not required to have default constructor. -Duplicate references encountered in the object-model will be -maintained. Supports circular references. By implementing an -interface, XStream can serialize directly to/from any tree -structure (not just XML). Strategies can be registered allowing -customization of how particular types are represented as XML. -When an exception occurs due to malformed XML, detailed diagnostics +XStream is a simple library to serialize objects to XML +and back again. A high level facade is supplied that +simplifies common use cases. Custom objects can be serialized +without need for specifying mappings. Speed and low memory +footprint are a crucial part of the design, making it suitable +for large object graphs or systems with high message throughput. +No information is duplicated that can be obtained via reflection. +This results in XML that is easier to read for humans and more +compact than native Java serialization. XStream serializes internal +fields, including private and final. Supports non-public and inner +classes. Classes are not required to have default constructor. +Duplicate references encountered in the object-model will be +maintained. Supports circular references. By implementing an +interface, XStream can serialize directly to/from any tree +structure (not just XML). Strategies can be registered allowing +customization of how particular types are represented as XML. +When an exception occurs due to malformed XML, detailed diagnostics are provided to help isolate and fix the problem. -%package -n %{name}-benchmark -Summary: Benchmark module for %{name} -%description -n %{name}-benchmark -Benchmark module for %{name}. -%{?javadoc_package} +%package javadoc +Summary: Javadoc for %{name} +Group: Documentation +Requires: jpackage-utils + +%description javadoc +%{name} API documentation. + %prep -# -n: base directory name -%autosetup -n %{name}-%{version} -# delete precompiled jar and class files -find -type f '(' -iname '*.jar' -o -iname '*.class' ')' -print -delete -# change javax to jakarta -# https://jakarta.ee/about/faq#What_happened_with_javax.*_namespace? -%pom_change_dep -r javax.activation:activation jakarta.activation:jakarta.activation-api:1 -%pom_change_dep -r javax.xml.bind:jaxb-api jakarta.xml.bind:jakarta.xml.bind-api:2 -# remove dependency plugin -%pom_remove_plugin -r :maven-dependency-plugin -# optional dep: activation -%if %{without activation} -%pom_remove_dep -r jakarta.activation:jakarta.activation-api -rm xstream/src/java/com/thoughtworks/xstream/converters/extended/ActivationDataFlavorConverter.java +%setup -qn %{name}-%{version} +%patch0 -p1 +find . -name "*.jar" -delete + +%if %with test +# This test requires megginson's sax2 +rm -f xstream/src/test/com/thoughtworks/xstream/io/xml/SaxWriterTest.java %endif -# optional dep: cglib -%if %{without cglib} -%pom_remove_dep -r cglib:cglib-nodep -rm xstream/src/java/com/thoughtworks/xstream/converters/reflection/CGLIBEnhancedConverter.java -rm xstream/src/java/com/thoughtworks/xstream/mapper/CGLIBMapper.java -rm xstream/src/java/com/thoughtworks/xstream/security/CGLIBProxyTypePermission.java -%endif -# optional dep: dom4j -%if %{without dom4j} -%pom_remove_dep -r dom4j:dom4j -rm xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JDriver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JReader.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JWriter.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/Dom4JXmlWriter.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamDom4J.java -%endif -# optional dep: jdom -%if %{without jdom} -%pom_remove_dep -r org.jdom:jdom -rm xstream/src/java/com/thoughtworks/xstream/io/xml/JDomDriver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/JDomReader.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/JDomWriter.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamJDom.java -%endif -# optional dep: jdom2 -%if %{without jdom2} -%pom_remove_dep -r org.jdom:jdom2 -rm xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Driver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Reader.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/JDom2Writer.java -%endif -# optional dep: jettison -%if %{without jettison} -%pom_remove_dep -r org.codehaus.jettison:jettison -rm xstream/src/java/com/thoughtworks/xstream/io/json/JettisonMappedXmlDriver.java -rm xstream/src/java/com/thoughtworks/xstream/io/json/JettisonStaxWriter.java -%endif -# optional dep: joda-time -%if %{without joda-time} -%pom_remove_dep -r joda-time:joda-time -rm xstream/src/java/com/thoughtworks/xstream/core/util/ISO8601JodaTimeConverter.java -%endif -# optional dep: kxml2 -%if %{without kxml2} -%pom_remove_dep -r net.sf.kxml:kxml2-min -rm xstream/src/java/com/thoughtworks/xstream/io/xml/KXml2DomDriver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/KXml2Driver.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamKXml2DOM.java -%endif -# optional dep: stax -%if %{without stax} -%pom_remove_dep -r stax:stax -%pom_remove_dep -r stax:stax-api -rm xstream/src/java/com/thoughtworks/xstream/io/xml/BEAStaxDriver.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamBEAStax.java -%endif -# optional dep: woodstox -%if %{without woodstox} -%pom_remove_dep -r org.codehaus.woodstox:wstx-asl -%pom_remove_dep -r com.fasterxml.woodstox:woodstox-core -rm xstream/src/java/com/thoughtworks/xstream/io/xml/WstxDriver.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamWoodstox.java -%endif -# optional dep: xom -%if %{without xom} -%pom_remove_dep -r xom:xom -rm xstream/src/java/com/thoughtworks/xstream/io/xml/XomDriver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/XomReader.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/XomWriter.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXom.java -%endif -# optional dep: xpp3 -%if %{without xpp3} -%pom_remove_dep -r xpp3:xpp3_min -rm xstream/src/java/com/thoughtworks/xstream/io/xml/Xpp3DomDriver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/Xpp3Driver.java -rm xstream/src/java/com/thoughtworks/xstream/io/xml/xppdom/Xpp3DomBuilder.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3.java -rm xstream-benchmark/src/java/com/thoughtworks/xstream/tools/benchmark/products/XStreamXpp3DOM.java -%endif -# disable module distribution -%pom_disable_module %{name}-distribution -# disable module hibernate -%pom_disable_module %{name}-hibernate -# disable module jmh -%pom_disable_module %{name}-jmh -# don't install parent package -%mvn_package :%{name}-parent __noinstall + %build -%mvn_build -s -f -- -Dversion.java.5=1.8 -Dversion.java.6=1.8 -Dversion.java.source=1.8 -Dversion.java.target=1.8 +# Replace bundled tars +pushd xstream/lib +ln -sf $(build-classpath cglib) +ln -sf $(build-classpath commons-lang) +ln -sf $(build-classpath dom4j) +ln -sf $(build-classpath jdom) +ln -sf $(build-classpath jettison) +ln -sf $(build-classpath joda-time) +ln -sf $(build-classpath junit) +ln -sf $(build-classpath oro) +ln -sf $(build-classpath bea-stax-ri) +ln -sf $(build-classpath bea-stax-api) +ln -sf $(build-classpath xom) +ln -sf $(build-classpath xpp3) +%if %with test +ln -sf $(build-classpath jmock) +ln -sf $(build-classpath wstx/wstx-asl) +%endif +popd + +# Build +pushd xstream +%if %with test +ant library javadoc +%else +ant benchmark:compile jar javadoc +%endif +popd + %install -%mvn_install +rm -rf $RPM_BUILD_ROOT + +# Directory structure +install -d $RPM_BUILD_ROOT%{_javadir} +install -d $RPM_BUILD_ROOT%{_javadocdir} + +# Main jar +pushd xstream +install -p -m644 target/xstream-SNAPSHOT.jar \ + $RPM_BUILD_ROOT%{_javadir}/%{name}.jar + +# Benchmarks +install -p -m644 target/xstream-benchmark-SNAPSHOT.jar \ + $RPM_BUILD_ROOT%{_javadir}/%{name}-benchmark.jar + +# API Documentation +cp -pr target/javadoc $RPM_BUILD_ROOT%{_javadocdir}/%{name} +popd + +# POMs +install -d -m 755 %{buildroot}%{_mavenpomdir} +install -pm 644 pom.xml \ + %{buildroot}%{_mavenpomdir}/JPP-%{name}-parent.pom +%add_maven_depmap JPP-%{name}-parent.pom + +install -pm 644 xstream/pom.xml \ + %{buildroot}%{_mavenpomdir}/JPP-%{name}.pom +%add_maven_depmap + + +# Workaround for RPM bug #646523 - can't change symlink to directory +# TODO: Remove this in F-22 +%pretrans javadoc -p +dir = "%{_javadocdir}/%{name}" +dummy = posix.readlink(dir) and os.remove(dir) + + +%files +%{_javadir}/*.jar +%{_mavenpomdir}/* +%{_mavendepmapfragdir}/* +%doc LICENSE.txt + + +%files javadoc +%{_javadocdir}/%{name} +%doc LICENSE.txt -%files -n %{name} -f .mfiles-%{name} -%license LICENSE.txt -%doc README.txt -%files -n %{name}-benchmark -f .mfiles-%{name}-benchmark -%license LICENSE.txt -%doc README.txt %changelog -* Fri Jul 17 2026 Fedora Release Engineering - 1.4.21-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild - -* Mon Mar 09 2026 Ondřej Pohořelský - 1.4.21-1 -- New upstream release 1.4.21 - -* Sat Jan 17 2026 Fedora Release Engineering - 1.4.20-11 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild - -* Tue Jul 29 2025 jiri vanek - 1.4.20-10 -- Rebuilt for java-25-openjdk as preffered jdk - -* Fri Jul 25 2025 Fedora Release Engineering - 1.4.20-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Sun Jan 19 2025 Fedora Release Engineering - 1.4.20-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Wed Sep 04 2024 Miroslav Suchý - 1.4.20-7 -- convert license to SPDX - -* Sat Jul 20 2024 Fedora Release Engineering - 1.4.20-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Tue Feb 27 2024 Jiri Vanek - 1.4.20-5 -- Rebuilt for java-21-openjdk as system jdk - -* Mon Jan 29 2024 Fedora Release Engineering - 1.4.20-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Sat Jul 22 2023 Fedora Release Engineering - 1.4.20-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Mon Feb 20 2023 Didik Supriadi - 1.4.20-2 -- Depend on compat versions of activation and XML bind (by @mkoncek) -- Re-enable activation - -* Mon Feb 20 2023 Didik Supriadi - 1.4.20-1 -- New upstream release 1.4.20 -- Disable activation - -* Sat Jan 21 2023 Fedora Release Engineering - 1.4.19-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Sat Jul 23 2022 Fedora Release Engineering - 1.4.19-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Fri Jul 08 2022 Jiri Vanek - 1.4.19-3 -- Rebuilt for Drop i686 JDKs - -* Sat Feb 05 2022 Jiri Vanek - 1.4.19-2 -- Rebuilt for java-17-openjdk as system jdk - -* Sat Jan 29 2022 Didik Supriadi - 1.4.19-1 -- New upstream release 1.4.19 - -* Sat Jan 22 2022 Fedora Release Engineering - 1.4.18-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Mon Oct 04 2021 Didik Supriadi - 1.4.18-2 -- Enable activation, cglib, dom4j, jdom, and jdom2 - -* Fri Oct 01 2021 Didik Supriadi - 1.4.18-1 -- Update to version 1.4.18 - -* Fri Jul 23 2021 Fedora Release Engineering - 1.4.14-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Thu Jan 28 2021 Fedora Release Engineering - 1.4.14-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Tue Nov 17 2020 Ding-Yi Chen - 1.4.14-1 -- Upstream update to 1.4.14 - -* Fri Aug 07 2020 Mat Booth - 1.4.12-6 -- Allow building on JDK11 - -* Wed Jul 29 2020 Fedora Release Engineering - 1.4.12-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Sat Jul 11 2020 Jiri Vanek - 1.4.12-4 -- Rebuilt for JDK-11, see https://fedoraproject.org/wiki/Changes/Java11 - -* Wed Jun 17 2020 Fabio Valentini - 1.4.12-3 -- Disable unused optional dom4j, jdom, jdom2, kxml, and woodstox support. - -* Mon Jun 08 2020 Fabio Valentini - 1.4.12-2 -- Disable optional support for joda-time by default. - -* Mon Apr 27 2020 Fabio Valentini - 1.4.12-1 -- Update to version 1.4.12. -- Disable optional support for BEA Stax by default. - -* Fri Jan 31 2020 Fedora Release Engineering - 1.4.11.1-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Tue Nov 05 2019 Fabio Valentini - 1.4.11.1-4 -- Use Java version override compatible with both xmvn 3.0.0 and 3.1.0. - -* Fri Jul 26 2019 Fabio Valentini - 1.4.11.1-3 -- Disable hibernate support by default. - -* Tue Mar 05 2019 Mat Booth - 1.4.11.1-2 -- Allow building with reduced dependency set - -* Thu Feb 14 2019 Mat Booth - 1.4.11.1-1 -- Update to latest upstream release - -* Sun Feb 03 2019 Fedora Release Engineering - 1.4.9-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Sat Jul 14 2018 Fedora Release Engineering - 1.4.9-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Fri Feb 09 2018 Fedora Release Engineering - 1.4.9-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Thu Jul 27 2017 Fedora Release Engineering - 1.4.9-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Wed Apr 12 2017 Michael Simacek - 1.4.9-5 -- Backport fix for void deserialization -- Resolves rhbz#1441542 -- Update upstream URL - -* Mon Feb 06 2017 Michael Simacek - 1.4.9-4 -- Add conditional for hibernate - -* Mon Jul 18 2016 Michael Simacek - 1.4.9-3 -- Regenerate buildrequires - -* Wed Jun 15 2016 Mikolaj Izdebski - 1.4.9-2 -- Regenerate build-requires - -* Wed Mar 30 2016 Michal Srb - 1.4.9-1 -- Update to 1.4.9 -- Resolves: CVE-2016-3674 - -* Fri Feb 05 2016 Fedora Release Engineering - 1.4.8-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild - -* Tue Jan 19 2016 Mikolaj Izdebski - 1.4.8-3 -- Fix dependency on xpp3 - -* Fri Jun 19 2015 Fedora Release Engineering - 1.4.8-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Thu Feb 19 2015 Michal Srb - 1.4.8-1 -- Update to upstream version 1.4.8 - -* Mon Nov 10 2014 Michael Simacek - 1.4.7-9 -- Change org.json:json dependency scope to test - -* Wed Nov 5 2014 Mikolaj Izdebski - 1.4.7-8 -- Remove workaround for RPM bug #646523 - -* Fri Oct 24 2014 Mikolaj Izdebski - 1.4.7-7 -- Fix dependencies in parent POM - -* Mon Aug 4 2014 Mikolaj Izdebski - 1.4.7-6 -- Fix build-requires on codehaus-parent - -* Sun Jun 08 2014 Fedora Release Engineering - 1.4.7-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild - -* Fri Mar 07 2014 Michael Simacek - 1.4.7-4 -- Split into subpackages - -* Tue Mar 04 2014 Stanislav Ochotnicky - 1.4.7-3 -- Use Requires: java-headless rebuild (#1067528) - -* Wed Feb 19 2014 Michal Srb - 1.4.7-2 -- Spec file cleanup -- Fix BR -- Build with kxml2 and json - -* Mon Feb 10 2014 Michal Srb - 1.4.7-1 -- Update to latest upstream release 1.4.7 - -* Thu Jan 02 2014 Michal Srb - 1.4.6-1 -- Update to upstream release 1.4.6 - -* Thu Oct 24 2013 Mikolaj Izdebski - 1.4.5-3 -- Rebuild to move arch-independant JARs out of %%_jnidir -* Wed Oct 23 2013 Mikolaj Izdebski - 1.4.5-2 -- Rebuild to regenerate broken POM files -- Related: rhbz#1021484 - -* Sun Oct 20 2013 Matt Spaulding 1.4.5-1 -- update to 1.4.5 - -* Tue Aug 20 2013 gil cattaneo 1.4.4-1 -- update to 1.4.4 -- switch to XMvn +* Tue Feb 11 2014 Mikolaj Izdebski - 1.3.1-9 +- Apply upstream security patch +- Resolves: CVE-2013-7285 * Sun Aug 04 2013 Fedora Release Engineering - 1.3.1-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild