Merge pull request #6087 from smowton/smowton/admin/rest-xss-tests

Java: Add Spring XSS tests
This commit is contained in:
Anders Schack-Mulligen
2021-07-27 14:09:34 +02:00
committed by GitHub
7 changed files with 843 additions and 42 deletions

View File

@@ -0,0 +1,160 @@
import org.springframework.http.ResponseEntity;
import org.springframework.http.MediaType;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
public class SpringXSS {
@GetMapping
public static ResponseEntity<String> specificContentType(boolean safeContentType, boolean chainDirectly, String userControlled) {
ResponseEntity.BodyBuilder builder = ResponseEntity.ok();
if(safeContentType) {
if(chainDirectly) {
return builder.contentType(MediaType.TEXT_HTML).body(userControlled); // $xss
}
else {
ResponseEntity.BodyBuilder builder2 = builder.contentType(MediaType.TEXT_HTML);
return builder2.body(userControlled); // $xss
}
}
else {
if(chainDirectly) {
return builder.contentType(MediaType.APPLICATION_JSON).body(userControlled); // $SPURIOUS: xss
}
else {
ResponseEntity.BodyBuilder builder2 = builder.contentType(MediaType.APPLICATION_JSON);
return builder2.body(userControlled); // $SPURIOUS: xss
}
}
}
@GetMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
public static ResponseEntity<String> methodContentTypeSafe(String userControlled) {
return ResponseEntity.ok(userControlled);
}
@PostMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
public static ResponseEntity<String> methodContentTypeSafePost(String userControlled) {
return ResponseEntity.ok(userControlled);
}
@RequestMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
public static ResponseEntity<String> methodContentTypeSafeRequest(String userControlled) {
return ResponseEntity.ok(userControlled);
}
@GetMapping(value = "/xyz", produces = "application/json")
public static ResponseEntity<String> methodContentTypeSafeStringLiteral(String userControlled) {
return ResponseEntity.ok(userControlled);
}
@GetMapping(value = "/xyz", produces = MediaType.TEXT_HTML_VALUE)
public static ResponseEntity<String> methodContentTypeUnsafe(String userControlled) {
return ResponseEntity.ok(userControlled); // $MISSING: xss
}
@GetMapping(value = "/xyz", produces = "text/html")
public static ResponseEntity<String> methodContentTypeUnsafeStringLiteral(String userControlled) {
return ResponseEntity.ok(userControlled); // $xss
}
@GetMapping(value = "/xyz", produces = {MediaType.TEXT_HTML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public static ResponseEntity<String> methodContentTypeMaybeSafe(String userControlled) {
return ResponseEntity.ok(userControlled); // $xss
}
@GetMapping(value = "/xyz", produces = MediaType.APPLICATION_JSON_VALUE)
public static ResponseEntity<String> methodContentTypeSafeOverriddenWithUnsafe(String userControlled) {
return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(userControlled); // $MISSING: xss
}
@GetMapping(value = "/xyz", produces = MediaType.TEXT_HTML_VALUE)
public static ResponseEntity<String> methodContentTypeUnsafeOverriddenWithSafe(String userControlled) {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(userControlled);
}
@GetMapping(value = "/xyz", produces = {"text/html", "application/json"})
public static ResponseEntity<String> methodContentTypeMaybeSafeStringLiterals(String userControlled, int constructionMethod) {
// Also try out some alternative constructors for the ResponseEntity:
switch(constructionMethod) {
case 0:
return ResponseEntity.ok(userControlled); // $xss
case 1:
return ResponseEntity.of(Optional.of(userControlled)); // $xss
case 2:
return ResponseEntity.ok().body(userControlled); // $xss
case 3:
return new ResponseEntity<String>(userControlled, HttpStatus.OK); // $xss
default:
return null;
}
}
@RestController
@RequestMapping(produces = {"application/json"})
private static class ClassContentTypeSafe {
@GetMapping(value = "/abc")
public ResponseEntity<String> test(String userControlled) {
return ResponseEntity.ok(userControlled); // $SPURIOUS: xss
}
@GetMapping(value = "/abc")
public String testDirectReturn(String userControlled) {
return userControlled; // $SPURIOUS: xss
}
@GetMapping(value = "/xyz", produces = {"text/html"})
public ResponseEntity<String> overridesWithUnsafe(String userControlled) {
return ResponseEntity.ok(userControlled); // $xss
}
@GetMapping(value = "/abc")
public ResponseEntity<String> overridesWithUnsafe2(String userControlled) {
return ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body(userControlled); // $xss
}
}
@RestController
@RequestMapping(produces = {"text/html"})
private static class ClassContentTypeUnsafe {
@GetMapping(value = "/abc")
public ResponseEntity<String> test(String userControlled) {
return ResponseEntity.ok(userControlled); // $xss
}
@GetMapping(value = "/abc")
public String testDirectReturn(String userControlled) {
return userControlled; // $xss
}
@GetMapping(value = "/xyz", produces = {"application/json"})
public ResponseEntity<String> overridesWithSafe(String userControlled) {
return ResponseEntity.ok(userControlled); // $SPURIOUS: xss
}
@GetMapping(value = "/abc")
public ResponseEntity<String> overridesWithSafe2(String userControlled) {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(userControlled); // $SPURIOUS: xss
}
}
@GetMapping(value = "/abc")
public static ResponseEntity<String> entityWithNoMediaType(String userControlled) {
return ResponseEntity.ok(userControlled); // $xss
}
@GetMapping(value = "/abc")
public static String stringWithNoMediaType(String userControlled) {
return userControlled; // $xss
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/javax-ws-rs-api-2.1.1/
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/javax-ws-rs-api-2.1.1/:${testdir}/../../../../../stubs/springframework-5.3.8

View File

@@ -62,33 +62,33 @@ public class MediaType extends MimeType implements Serializable
public static MediaType asMediaType(MimeType p0){ return null; }
public static MediaType parseMediaType(String p0){ return null; }
public static MediaType valueOf(String p0){ return null; }
public static String ALL_VALUE = null;
public static String APPLICATION_ATOM_XML_VALUE = null;
public static String APPLICATION_CBOR_VALUE = null;
public static String APPLICATION_FORM_URLENCODED_VALUE = null;
public static String APPLICATION_JSON_UTF8_VALUE = null;
public static String APPLICATION_JSON_VALUE = null;
public static String APPLICATION_NDJSON_VALUE = null;
public static String APPLICATION_OCTET_STREAM_VALUE = null;
public static String APPLICATION_PDF_VALUE = null;
public static String APPLICATION_PROBLEM_JSON_UTF8_VALUE = null;
public static String APPLICATION_PROBLEM_JSON_VALUE = null;
public static String APPLICATION_PROBLEM_XML_VALUE = null;
public static String APPLICATION_RSS_XML_VALUE = null;
public static String APPLICATION_STREAM_JSON_VALUE = null;
public static String APPLICATION_XHTML_XML_VALUE = null;
public static String APPLICATION_XML_VALUE = null;
public static String IMAGE_GIF_VALUE = null;
public static String IMAGE_JPEG_VALUE = null;
public static String IMAGE_PNG_VALUE = null;
public static String MULTIPART_FORM_DATA_VALUE = null;
public static String MULTIPART_MIXED_VALUE = null;
public static String MULTIPART_RELATED_VALUE = null;
public static String TEXT_EVENT_STREAM_VALUE = null;
public static String TEXT_HTML_VALUE = null;
public static String TEXT_MARKDOWN_VALUE = null;
public static String TEXT_PLAIN_VALUE = null;
public static String TEXT_XML_VALUE = null;
public static final String ALL_VALUE = "";
public static final String APPLICATION_ATOM_XML_VALUE = "";
public static final String APPLICATION_CBOR_VALUE = "";
public static final String APPLICATION_FORM_URLENCODED_VALUE = "";
public static final String APPLICATION_JSON_UTF8_VALUE = "";
public static final String APPLICATION_JSON_VALUE = "";
public static final String APPLICATION_NDJSON_VALUE = "";
public static final String APPLICATION_OCTET_STREAM_VALUE = "";
public static final String APPLICATION_PDF_VALUE = "";
public static final String APPLICATION_PROBLEM_JSON_UTF8_VALUE = "";
public static final String APPLICATION_PROBLEM_JSON_VALUE = "";
public static final String APPLICATION_PROBLEM_XML_VALUE = "";
public static final String APPLICATION_RSS_XML_VALUE = "";
public static final String APPLICATION_STREAM_JSON_VALUE = "";
public static final String APPLICATION_XHTML_XML_VALUE = "";
public static final String APPLICATION_XML_VALUE = "";
public static final String IMAGE_GIF_VALUE = "";
public static final String IMAGE_JPEG_VALUE = "";
public static final String IMAGE_PNG_VALUE = "";
public static final String MULTIPART_FORM_DATA_VALUE = "";
public static final String MULTIPART_MIXED_VALUE = "";
public static final String MULTIPART_RELATED_VALUE = "";
public static final String TEXT_EVENT_STREAM_VALUE = "";
public static final String TEXT_HTML_VALUE = "";
public static final String TEXT_MARKDOWN_VALUE = "";
public static final String TEXT_PLAIN_VALUE = "";
public static final String TEXT_XML_VALUE = "";
public static String toString(Collection<MediaType> p0){ return null; }
public static void sortByQualityValue(List<MediaType> p0){}
public static void sortBySpecificity(List<MediaType> p0){}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
@@ -6,11 +22,69 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* Annotation for mapping HTTP {@code POST} requests onto specific handler
* methods.
*
* <p>Specifically, {@code @PostMapping} is a <em>composed annotation</em> that
* acts as a shortcut for {@code @RequestMapping(method = RequestMethod.POST)}.
*
* @author Sam Brannen
* @since 4.3
* @see GetMapping
* @see PutMapping
* @see DeleteMapping
* @see PatchMapping
* @see RequestMapping
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.POST)
public @interface PostMapping {
String[] value() default {};
}
/**
* Alias for {@link RequestMapping#name}.
*/
@AliasFor(annotation = RequestMapping.class)
String name() default "";
/**
* Alias for {@link RequestMapping#value}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] value() default {};
/**
* Alias for {@link RequestMapping#path}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] path() default {};
/**
* Alias for {@link RequestMapping#params}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] params() default {};
/**
* Alias for {@link RequestMapping#headers}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {};
/**
* Alias for {@link RequestMapping#consumes}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default {};
/**
* Alias for {@link RequestMapping#produces}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] produces() default {};
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
@@ -5,28 +21,189 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(value=RetentionPolicy.RUNTIME)
/**
* Annotation for mapping web requests onto methods in request-handling classes
* with flexible method signatures.
*
* <p>Both Spring MVC and Spring WebFlux support this annotation through a
* {@code RequestMappingHandlerMapping} and {@code RequestMappingHandlerAdapter}
* in their respective modules and package structure. For the exact list of
* supported handler method arguments and return types in each, please use the
* reference documentation links below:
* <ul>
* <li>Spring MVC
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-arguments">Method Arguments</a>
* and
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-return-types">Return Values</a>
* </li>
* <li>Spring WebFlux
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-arguments">Method Arguments</a>
* and
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-ann-return-types">Return Values</a>
* </li>
* </ul>
*
* <p><strong>Note:</strong> This annotation can be used both at the class and
* at the method level. In most cases, at the method level applications will
* prefer to use one of the HTTP method specific variants
* {@link GetMapping @GetMapping}, {@link PostMapping @PostMapping},
* {@link PutMapping @PutMapping}, {@link DeleteMapping @DeleteMapping}, or
* {@link PatchMapping @PatchMapping}.</p>
*
* <p><b>NOTE:</b> When using controller interfaces (e.g. for AOP proxying),
* make sure to consistently put <i>all</i> your mapping annotations - such as
* {@code @RequestMapping} and {@code @SessionAttributes} - on
* the controller <i>interface</i> rather than on the implementation class.
*
* @author Juergen Hoeller
* @author Arjen Poutsma
* @author Sam Brannen
* @since 2.5
* @see GetMapping
* @see PostMapping
* @see PutMapping
* @see DeleteMapping
* @see PatchMapping
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
/**
* Assign a name to this mapping.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used on both levels, a combined name is derived by concatenation
* with "#" as separator.
* @see org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder
* @see org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
*/
String name() default "";
@AliasFor("value")
String[] path() default {};
/**
* The primary mapping expressed by this annotation.
* <p>This is an alias for {@link #path}. For example,
* {@code @RequestMapping("/foo")} is equivalent to
* {@code @RequestMapping(path="/foo")}.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit
* this primary mapping, narrowing it for a specific handler method.
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
* explicitly is effectively mapped to an empty path.
*/
@AliasFor("path")
String[] value() default {};
RequestMethod[] method() default {};
/**
* The path mapping URIs (e.g. {@code "/profile"}).
* <p>Ant-style path patterns are also supported (e.g. {@code "/profile/**"}).
* At the method level, relative paths (e.g. {@code "edit"}) are supported
* within the primary mapping expressed at the type level.
* Path mapping URIs may contain placeholders (e.g. <code>"/${profile_path}"</code>).
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit
* this primary mapping, narrowing it for a specific handler method.
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
* explicitly is effectively mapped to an empty path.
* @since 4.2
*/
@AliasFor("value")
String[] path() default {};
String[] params() default {};
/**
* The HTTP request methods to map to, narrowing the primary mapping:
* GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit this
* HTTP method restriction.
*/
RequestMethod[] method() default {};
String[] headers() default {};
/**
* The parameters of the mapped request, narrowing the primary mapping.
* <p>Same format for any environment: a sequence of "myParam=myValue" style
* expressions, with a request only mapped if each such parameter is found
* to have the given value. Expressions can be negated by using the "!=" operator,
* as in "myParam!=myValue". "myParam" style expressions are also supported,
* with such parameters having to be present in the request (allowed to have
* any value). Finally, "!myParam" style expressions indicate that the
* specified parameter is <i>not</i> supposed to be present in the request.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit this
* parameter restriction.
*/
String[] params() default {};
String[] consumes() default {};
/**
* The headers of the mapped request, narrowing the primary mapping.
* <p>Same format for any environment: a sequence of "My-Header=myValue" style
* expressions, with a request only mapped if each such header is found
* to have the given value. Expressions can be negated by using the "!=" operator,
* as in "My-Header!=myValue". "My-Header" style expressions are also supported,
* with such headers having to be present in the request (allowed to have
* any value). Finally, "!My-Header" style expressions indicate that the
* specified header is <i>not</i> supposed to be present in the request.
* <p>Also supports media type wildcards (*), for headers such as Accept
* and Content-Type. For instance,
* <pre class="code">
* &#064;RequestMapping(value = "/something", headers = "content-type=text/*")
* </pre>
* will match requests with a Content-Type of "text/html", "text/plain", etc.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit this
* header restriction.
* @see org.springframework.http.MediaType
*/
String[] headers() default {};
/**
* Narrows the primary mapping by media types that can be consumed by the
* mapped handler. Consists of one or more media types one of which must
* match to the request {@code Content-Type} header. Examples:
* <pre class="code">
* consumes = "text/plain"
* consumes = {"text/plain", "application/*"}
* consumes = MediaType.TEXT_PLAIN_VALUE
* </pre>
* Expressions can be negated by using the "!" operator, as in
* "!text/plain", which matches all requests with a {@code Content-Type}
* other than "text/plain".
* <p><b>Supported at the type level as well as at the method level!</b>
* If specified at both levels, the method level consumes condition overrides
* the type level condition.
* @see org.springframework.http.MediaType
* @see javax.servlet.http.HttpServletRequest#getContentType()
*/
String[] consumes() default {};
/**
* Narrows the primary mapping by media types that can be produced by the
* mapped handler. Consists of one or more media types one of which must
* be chosen via content negotiation against the "acceptable" media types
* of the request. Typically those are extracted from the {@code "Accept"}
* header but may be derived from query parameters, or other. Examples:
* <pre class="code">
* produces = "text/plain"
* produces = {"text/plain", "application/*"}
* produces = MediaType.TEXT_PLAIN_VALUE
* produces = "text/plain;charset=UTF-8"
* </pre>
* <p>If a declared media type contains a parameter (e.g. "charset=UTF-8",
* "type=feed", "type=entry") and if a compatible media type from the request
* has that parameter too, then the parameter values must match. Otherwise
* if the media type from the request does not contain the parameter, it is
* assumed the client accepts any value.
* <p>Expressions can be negated by using the "!" operator, as in "!text/plain",
* which matches all requests with a {@code Accept} other than "text/plain".
* <p><b>Supported at the type level as well as at the method level!</b>
* If specified at both levels, the method level produces condition overrides
* the type level condition.
* @see org.springframework.http.MediaType
*/
String[] produces() default {};
String[] produces() default {};
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Controller;
/**
* A convenience annotation that is itself annotated with
* {@link Controller @Controller} and {@link ResponseBody @ResponseBody}.
* <p>
* Types that carry this annotation are treated as controllers where
* {@link RequestMapping @RequestMapping} methods assume
* {@link ResponseBody @ResponseBody} semantics by default.
*
* <p><b>NOTE:</b> {@code @RestController} is processed if an appropriate
* {@code HandlerMapping}-{@code HandlerAdapter} pair is configured such as the
* {@code RequestMappingHandlerMapping}-{@code RequestMappingHandlerAdapter}
* pair which are the default in the MVC Java config and the MVC namespace.
*
* @author Rossen Stoyanchev
* @author Sam Brannen
* @since 4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeSet;
import org.springframework.lang.Nullable;
/**
* Represents a MIME Type, as originally defined in RFC 2046 and subsequently
* used in other Internet protocols including HTTP.
*
* <p>This class, however, does not contain support for the q-parameters used
* in HTTP content negotiation. Those can be found in the subclass
* {@code org.springframework.http.MediaType} in the {@code spring-web} module.
*
* <p>Consists of a {@linkplain #getType() type} and a {@linkplain #getSubtype() subtype}.
* Also has functionality to parse MIME Type values from a {@code String} using
* {@link #valueOf(String)}. For more parsing options see {@link MimeTypeUtils}.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @author Sam Brannen
* @since 4.0
* @see MimeTypeUtils
*/
public class MimeType implements Comparable<MimeType>, Serializable {
protected static final String WILDCARD_TYPE = "";
/**
* Create a new {@code MimeType} for the given primary type.
* <p>The {@linkplain #getSubtype() subtype} is set to <code>"&#42;"</code>,
* and the parameters are empty.
* @param type the primary type
* @throws IllegalArgumentException if any of the parameters contains illegal characters
*/
public MimeType(String type) {
}
/**
* Create a new {@code MimeType} for the given primary type and subtype.
* <p>The parameters are empty.
* @param type the primary type
* @param subtype the subtype
* @throws IllegalArgumentException if any of the parameters contains illegal characters
*/
public MimeType(String type, String subtype) {
}
/**
* Create a new {@code MimeType} for the given type, subtype, and character set.
* @param type the primary type
* @param subtype the subtype
* @param charset the character set
* @throws IllegalArgumentException if any of the parameters contains illegal characters
*/
public MimeType(String type, String subtype, Charset charset) {
}
/**
* Copy-constructor that copies the type, subtype, parameters of the given {@code MimeType},
* and allows to set the specified character set.
* @param other the other MimeType
* @param charset the character set
* @throws IllegalArgumentException if any of the parameters contains illegal characters
* @since 4.3
*/
public MimeType(MimeType other, Charset charset) {
}
/**
* Copy-constructor that copies the type and subtype of the given {@code MimeType},
* and allows for different parameter.
* @param other the other MimeType
* @param parameters the parameters (may be {@code null})
* @throws IllegalArgumentException if any of the parameters contains illegal characters
*/
public MimeType(MimeType other, @Nullable Map<String, String> parameters) {
}
/**
* Create a new {@code MimeType} for the given type, subtype, and parameters.
* @param type the primary type
* @param subtype the subtype
* @param parameters the parameters (may be {@code null})
* @throws IllegalArgumentException if any of the parameters contains illegal characters
*/
public MimeType(String type, String subtype, @Nullable Map<String, String> parameters) {
}
/**
* Copy-constructor that copies the type, subtype and parameters of the given {@code MimeType},
* skipping checks performed in other constructors.
* @param other the other MimeType
* @since 5.3
*/
protected MimeType(MimeType other) {
}
protected void checkParameters(String parameter, String value) {
}
protected String unquote(String s) {
return null;
}
/**
* Indicates whether the {@linkplain #getType() type} is the wildcard character
* <code>&#42;</code> or not.
*/
public boolean isWildcardType() {
return false;
}
/**
* Indicates whether the {@linkplain #getSubtype() subtype} is the wildcard
* character <code>&#42;</code> or the wildcard character followed by a suffix
* (e.g. <code>&#42;+xml</code>).
* @return whether the subtype is a wildcard
*/
public boolean isWildcardSubtype() {
return false;
}
/**
* Indicates whether this MIME Type is concrete, i.e. whether neither the type
* nor the subtype is a wildcard character <code>&#42;</code>.
* @return whether this MIME Type is concrete
*/
public boolean isConcrete() {
return false;
}
/**
* Return the primary type.
*/
public String getType() {
return null;
}
/**
* Return the subtype.
*/
public String getSubtype() {
return null;
}
/**
* Return the subtype suffix as defined in RFC 6839.
* @since 5.3
*/
@Nullable
public String getSubtypeSuffix() {
return null;
}
/**
* Return the character set, as indicated by a {@code charset} parameter, if any.
* @return the character set, or {@code null} if not available
* @since 4.3
*/
@Nullable
public Charset getCharset() {
return null;
}
/**
* Return a generic parameter value, given a parameter name.
* @param name the parameter name
* @return the parameter value, or {@code null} if not present
*/
@Nullable
public String getParameter(String name) {
return null;
}
/**
* Return all generic parameter values.
* @return a read-only map (possibly empty, never {@code null})
*/
public Map<String, String> getParameters() {
return null;
}
/**
* Indicate whether this MIME Type includes the given MIME Type.
* <p>For instance, {@code text/*} includes {@code text/plain} and {@code text/html},
* and {@code application/*+xml} includes {@code application/soap+xml}, etc.
* This method is <b>not</b> symmetric.
* @param other the reference MIME Type with which to compare
* @return {@code true} if this MIME Type includes the given MIME Type;
* {@code false} otherwise
*/
public boolean includes(@Nullable MimeType other) {
return false;
}
/**
* Indicate whether this MIME Type is compatible with the given MIME Type.
* <p>For instance, {@code text/*} is compatible with {@code text/plain},
* {@code text/html}, and vice versa. In effect, this method is similar to
* {@link #includes}, except that it <b>is</b> symmetric.
* @param other the reference MIME Type with which to compare
* @return {@code true} if this MIME Type is compatible with the given MIME Type;
* {@code false} otherwise
*/
public boolean isCompatibleWith(@Nullable MimeType other) {
return false;
}
/**
* Similar to {@link #equals(Object)} but based on the type and subtype
* only, i.e. ignoring parameters.
* @param other the other mime type to compare to
* @return whether the two mime types have the same type and subtype
* @since 5.1.4
*/
public boolean equalsTypeAndSubtype(@Nullable MimeType other) {
return false;
}
/**
* Unlike {@link Collection#contains(Object)} which relies on
* {@link MimeType#equals(Object)}, this method only checks the type and the
* subtype, but otherwise ignores parameters.
* @param mimeTypes the list of mime types to perform the check against
* @return whether the list contains the given mime type
* @since 5.1.4
*/
public boolean isPresentIn(Collection<? extends MimeType> mimeTypes) {
return false;
}
@Override
public boolean equals(@Nullable Object other) {
return false;
}
/**
* Determine if the parameters in this {@code MimeType} and the supplied
* {@code MimeType} are equal, performing case-insensitive comparisons
* for {@link Charset Charsets}.
* @since 4.2
*/
private boolean parametersAreEqual(MimeType other) {
return true;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return null;
}
protected void appendTo(StringBuilder builder) {
}
/**
* Compares this MIME Type to another alphabetically.
* @param other the MIME Type to compare to
* @see MimeTypeUtils#sortBySpecificity(List)
*/
@Override
public int compareTo(MimeType other) {
return 0;
}
/**
* Parse the given String value into a {@code MimeType} object,
* with this method name following the 'valueOf' naming convention
* (as supported by {@link org.springframework.core.convert.ConversionService}.
* @see MimeTypeUtils#parseMimeType(String)
*/
public static MimeType valueOf(String value) {
return null;
}
/**
* Comparator to sort {@link MimeType MimeTypes} in order of specificity.
*
* @param <T> the type of mime types that may be compared by this comparator
*/
public static class SpecificityComparator<T extends MimeType> implements Comparator<T> {
@Override
public int compare(T mimeType1, T mimeType2) {
return 0;
}
protected int compareParameters(T mimeType1, T mimeType2) {
return 0;
}
}
}