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
);
22 * Generates a new {@link DataURI} object that follows
23 * <a href="https://datatracker.ietf.org/doc/html/rfc2397">RFC 2397</a> from the given string.
25 * The {@code dataURI} must be of the form:
28 * data:[<mediatype>][;base64],<data>
31 * The {@code <mediatype>} is an Internet media type specification (with
32 * optional parameters.) The appearance of ";base64" means that the data
33 * is encoded as base64. Without ";base64", the data is represented using (ASCII) URL Escaped encoding.
34 * If {@code <mediatype>} is omitted, it defaults to {@link MimeUtils#PLAIN_TEXT}.
35 * Parameter values should use the URL Escaped encoding.
37 * @param dataURI the data URI
38 * @return a data URI object
39 * @throws IllegalArgumentException if the given string is not a valid data URI
41 public static DataURI
of(final String dataURI
) {
42 final var matcher
= DATA_URI_PATTERN
.matcher(dataURI
);
44 if (!matcher
.find()) {
45 throw new IllegalArgumentException("The given string is not a valid data URI.");
48 final Map
<String
, String
> parameters
= new HashMap
<>();
49 final var params
= matcher
.group("parameters");
51 final Matcher paramsMatcher
= PARAMETER_PATTERN
.matcher(params
);
52 while (paramsMatcher
.find()) {
53 final var key
= paramsMatcher
.group("key");
54 final var value
= URLDecoder
.decode(paramsMatcher
.group("value"), StandardCharsets
.UTF_8
);
55 parameters
.put(key
, value
);
59 final boolean isBase64
= matcher
.group("base64") != null;
62 data
= Base64
.getDecoder().decode(matcher
.group("data").getBytes(StandardCharsets
.UTF_8
));
64 data
= URLDecoder
.decode(matcher
.group("data"), StandardCharsets
.UTF_8
).getBytes(StandardCharsets
.UTF_8
);
67 return new DataURI(Optional
.ofNullable(matcher
.group("type")).orElse(MimeUtils
.PLAIN_TEXT
), parameters
, data
);