]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/util/DataURI.java
Add --ignore-stories flag to prevent receiving story messages
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / util / DataURI.java
1 package org.asamk.signal.manager.util;
2
3 import java.net.URLDecoder;
4 import java.nio.charset.StandardCharsets;
5 import java.util.Base64;
6 import java.util.HashMap;
7 import java.util.Map;
8 import java.util.Optional;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11
12 @SuppressWarnings({"java:S6218"})
13 public record DataURI(String mediaType, Map<String, String> parameter, byte[] data) {
14
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";
21
22 /**
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.
25 * <p>
26 * The {@code dataURI} must be of the form:
27 * <p>
28 * {@code
29 * data:[<mediatype>][;base64],<data>
30 * }
31 * <p>
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.
37 *
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
41 */
42 public static DataURI of(final String dataURI) {
43 final var matcher = DATA_URI_PATTERN.matcher(dataURI);
44
45 if (!matcher.find()) {
46 throw new IllegalArgumentException("The given string is not a valid data URI.");
47 }
48
49 final Map<String, String> parameters = new HashMap<>();
50 final var params = matcher.group("parameters");
51 if (params != null) {
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);
57 }
58 }
59
60 final boolean isBase64 = matcher.group("base64") != null;
61 final byte[] data;
62 if (isBase64) {
63 data = Base64.getDecoder().decode(matcher.group("data").getBytes(StandardCharsets.UTF_8));
64 } else {
65 data = URLDecoder.decode(matcher.group("data"), StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8);
66 }
67
68 return new DataURI(Optional.ofNullable(matcher.group("type")).orElse(DEFAULT_TYPE), parameters, data);
69 }
70 }