]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/util/Utils.java
Extra Database base class from AccountDatabase
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / util / Utils.java
1 package org.asamk.signal.manager.util;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.whispersystems.libsignal.IdentityKey;
6 import org.whispersystems.libsignal.fingerprint.Fingerprint;
7 import org.whispersystems.libsignal.fingerprint.NumericFingerprintGenerator;
8 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
9 import org.whispersystems.signalservice.api.util.StreamDetails;
10
11 import java.io.BufferedInputStream;
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.net.URLConnection;
17 import java.net.URLDecoder;
18 import java.nio.charset.StandardCharsets;
19 import java.nio.file.Files;
20 import java.util.HashMap;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.Spliterator;
24 import java.util.Spliterators;
25 import java.util.function.BiFunction;
26 import java.util.function.Consumer;
27 import java.util.stream.Stream;
28 import java.util.stream.StreamSupport;
29
30 public class Utils {
31
32 private final static Logger logger = LoggerFactory.getLogger(Utils.class);
33
34 public static String getFileMimeType(File file, String defaultMimeType) throws IOException {
35 var mime = Files.probeContentType(file.toPath());
36 if (mime == null) {
37 try (InputStream bufferedStream = new BufferedInputStream(new FileInputStream(file))) {
38 mime = URLConnection.guessContentTypeFromStream(bufferedStream);
39 }
40 }
41 if (mime == null) {
42 return defaultMimeType;
43 }
44 return mime;
45 }
46
47 public static StreamDetails createStreamDetailsFromFile(File file) throws IOException {
48 InputStream stream = new FileInputStream(file);
49 final var size = file.length();
50 final var mime = getFileMimeType(file, "application/octet-stream");
51 return new StreamDetails(stream, mime, size);
52 }
53
54 public static Fingerprint computeSafetyNumber(
55 boolean isUuidCapable,
56 SignalServiceAddress ownAddress,
57 IdentityKey ownIdentityKey,
58 SignalServiceAddress theirAddress,
59 IdentityKey theirIdentityKey
60 ) {
61 int version;
62 byte[] ownId;
63 byte[] theirId;
64
65 if (isUuidCapable) {
66 // Version 2: UUID user
67 version = 2;
68 ownId = ownAddress.getAci().toByteArray();
69 theirId = theirAddress.getAci().toByteArray();
70 } else {
71 // Version 1: E164 user
72 version = 1;
73 if (!ownAddress.getNumber().isPresent() || !theirAddress.getNumber().isPresent()) {
74 return null;
75 }
76 ownId = ownAddress.getNumber().get().getBytes();
77 theirId = theirAddress.getNumber().get().getBytes();
78 }
79
80 return new NumericFingerprintGenerator(5200).createFor(version,
81 ownId,
82 ownIdentityKey,
83 theirId,
84 theirIdentityKey);
85 }
86
87 public static Locale getDefaultLocale(Locale fallback) {
88 final var locale = Locale.getDefault();
89 if (locale == null) {
90 return fallback;
91 }
92 try {
93 Locale.LanguageRange.parse(locale.getLanguage() + "-" + locale.getCountry());
94 } catch (IllegalArgumentException e) {
95 logger.debug("Invalid locale, ignoring: {}", locale);
96 return fallback;
97 }
98
99 return locale;
100 }
101
102 public static <L, R, T> Stream<T> zip(Stream<L> leftStream, Stream<R> rightStream, BiFunction<L, R, T> combiner) {
103 Spliterator<L> lefts = leftStream.spliterator();
104 Spliterator<R> rights = rightStream.spliterator();
105 return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(Long.min(lefts.estimateSize(),
106 rights.estimateSize()), lefts.characteristics() & rights.characteristics()) {
107 @Override
108 public boolean tryAdvance(Consumer<? super T> action) {
109 return lefts.tryAdvance(left -> rights.tryAdvance(right -> action.accept(combiner.apply(left, right))));
110 }
111 }, leftStream.isParallel() || rightStream.isParallel());
112 }
113
114 public static Map<String, String> getQueryMap(String query) {
115 var params = query.split("&");
116 var map = new HashMap<String, String>();
117 for (var param : params) {
118 final var paramParts = param.split("=");
119 var name = URLDecoder.decode(paramParts[0], StandardCharsets.UTF_8);
120 var value = URLDecoder.decode(paramParts[1], StandardCharsets.UTF_8);
121 map.put(name, value);
122 }
123 return map;
124 }
125 }