1 package org
.asamk
.signal
.manager
.util
;
3 import java
.net
.URLDecoder
;
4 import java
.nio
.charset
.StandardCharsets
;
5 import java
.util
.Base64
;
6 import java
.util
.HashMap
;
8 import java
.util
.Optional
;
9 import java
.util
.regex
.Matcher
;
10 import java
.util
.regex
.Pattern
;
12 @SuppressWarnings({"java:S6218"})
13 public record DataURI(String mediaType
, Map
<String
, String
> parameter
, byte[] data
) {
15 public static final Pattern DATA_URI_PATTERN
= Pattern
.compile(
16 "\\Adata:(?<type>.+?/.+?)?(?<parameters>;.+?=.+?)?(?<base64>;base64)?,(?<data>.+)\\z",
17 Pattern
.CASE_INSENSITIVE
);
18 public static final Pattern PARAMETER_PATTERN
= Pattern
.compile("\\G;(?<key>.+)=(?<value>.+)",
19 Pattern
.CASE_INSENSITIVE
);
20 public static final String DEFAULT_TYPE
= "text/plain";
23 * Generates a new {@link DataURI} object that follows
24 * <a href="https://datatracker.ietf.org/doc/html/rfc2397">RFC 2397</a> from the given string.
26 * The {@code dataURI} must be of the form:
29 * data:[<mediatype>][;base64],<data>
32 * The {@code <mediatype>} is an Internet media type specification (with
33 * optional parameters.) The appearance of ";base64" means that the data
34 * is encoded as base64. Without ";base64", the data is represented using (ASCII) URL Escaped encoding.
35 * If {@code <mediatype>} is omitted, it defaults to {@link DataURI#DEFAULT_TYPE}.
36 * Parameter values should use the URL Escaped encoding.
38 * @param dataURI the data URI
39 * @return a data URI object
40 * @throws IllegalArgumentException if the given string is not a valid data URI
42 public static DataURI
of(final String dataURI
) {
43 final var matcher
= DATA_URI_PATTERN
.matcher(dataURI
);
45 if (!matcher
.find()) {
46 throw new IllegalArgumentException("The given string is not a valid data URI.");
49 final Map
<String
, String
> parameters
= new HashMap
<>();
50 final var params
= matcher
.group("parameters");
52 final Matcher paramsMatcher
= PARAMETER_PATTERN
.matcher(params
);
53 while (paramsMatcher
.find()) {
54 final var key
= paramsMatcher
.group("key");
55 final var value
= URLDecoder
.decode(paramsMatcher
.group("value"), StandardCharsets
.UTF_8
);
56 parameters
.put(key
, value
);
60 final boolean isBase64
= matcher
.group("base64") != null;
63 data
= Base64
.getDecoder().decode(matcher
.group("data").getBytes(StandardCharsets
.UTF_8
));
65 data
= URLDecoder
.decode(matcher
.group("data"), StandardCharsets
.UTF_8
).getBytes(StandardCharsets
.UTF_8
);
68 return new DataURI(Optional
.ofNullable(matcher
.group("type")).orElse(DEFAULT_TYPE
), parameters
, data
);