1 package org
.asamk
.signal
.manager
.util
;
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
;
11 import java
.io
.BufferedInputStream
;
13 import java
.io
.FileInputStream
;
14 import java
.io
.IOException
;
15 import java
.io
.InputStream
;
16 import java
.net
.URLConnection
;
17 import java
.nio
.file
.Files
;
18 import java
.util
.Locale
;
19 import java
.util
.Spliterator
;
20 import java
.util
.Spliterators
;
21 import java
.util
.function
.BiFunction
;
22 import java
.util
.function
.Consumer
;
23 import java
.util
.stream
.Stream
;
24 import java
.util
.stream
.StreamSupport
;
28 private final static Logger logger
= LoggerFactory
.getLogger(Utils
.class);
30 public static String
getFileMimeType(File file
, String defaultMimeType
) throws IOException
{
31 var mime
= Files
.probeContentType(file
.toPath());
33 try (InputStream bufferedStream
= new BufferedInputStream(new FileInputStream(file
))) {
34 mime
= URLConnection
.guessContentTypeFromStream(bufferedStream
);
38 return defaultMimeType
;
43 public static StreamDetails
createStreamDetailsFromFile(File file
) throws IOException
{
44 InputStream stream
= new FileInputStream(file
);
45 final var size
= file
.length();
46 final var mime
= getFileMimeType(file
, "application/octet-stream");
47 return new StreamDetails(stream
, mime
, size
);
50 public static Fingerprint
computeSafetyNumber(
51 boolean isUuidCapable
,
52 SignalServiceAddress ownAddress
,
53 IdentityKey ownIdentityKey
,
54 SignalServiceAddress theirAddress
,
55 IdentityKey theirIdentityKey
62 // Version 2: UUID user
64 ownId
= ownAddress
.getAci().toByteArray();
65 theirId
= theirAddress
.getAci().toByteArray();
67 // Version 1: E164 user
69 if (!ownAddress
.getNumber().isPresent() || !theirAddress
.getNumber().isPresent()) {
72 ownId
= ownAddress
.getNumber().get().getBytes();
73 theirId
= theirAddress
.getNumber().get().getBytes();
76 return new NumericFingerprintGenerator(5200).createFor(version
,
83 public static Locale
getDefaultLocale() {
84 final var locale
= Locale
.getDefault();
89 Locale
.LanguageRange
.parse(locale
.getLanguage() + "-" + locale
.getCountry());
90 } catch (IllegalArgumentException e
) {
91 logger
.debug("Invalid locale, ignoring: {}", locale
);
98 public static <L
, R
, T
> Stream
<T
> zip(Stream
<L
> leftStream
, Stream
<R
> rightStream
, BiFunction
<L
, R
, T
> combiner
) {
99 Spliterator
<L
> lefts
= leftStream
.spliterator();
100 Spliterator
<R
> rights
= rightStream
.spliterator();
101 return StreamSupport
.stream(new Spliterators
.AbstractSpliterator
<T
>(Long
.min(lefts
.estimateSize(),
102 rights
.estimateSize()), lefts
.characteristics() & rights
.characteristics()) {
104 public boolean tryAdvance(Consumer
<?
super T
> action
) {
105 return lefts
.tryAdvance(left
-> rights
.tryAdvance(right
-> action
.accept(combiner
.apply(left
, right
))));
107 }, leftStream
.isParallel() || rightStream
.isParallel());