1 /* 2 * Copyright (C) 2020 Finn Herzfeld 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package io.finn.signald.storage; 19 20 import com.fasterxml.jackson.annotation.JsonIgnore; 21 import io.finn.signald.db.Recipient; 22 import java.util.ArrayList; 23 import java.util.List; 24 import java.util.UUID; 25 import org.signal.zkgroup.profiles.ProfileKey; 26 import org.signal.zkgroup.profiles.ProfileKeyCredential; 27 import org.whispersystems.libsignal.util.guava.Optional; 28 import org.whispersystems.signalservice.api.push.SignalServiceAddress; 29 30 public class ProfileCredentialStore { 31 private static boolean unsaved = false; 32 public List<ProfileAndCredentialEntry> profiles = new ArrayList<>(); 33 34 @JsonIgnore getProfileKeyCredential(UUID uuid)35 public ProfileKeyCredential getProfileKeyCredential(UUID uuid) { 36 ProfileAndCredentialEntry entry = get(new SignalServiceAddress(uuid, Optional.absent())); 37 if (entry != null) { 38 return entry.getProfileKeyCredential(); 39 } 40 return null; 41 } 42 43 @JsonIgnore get(Recipient recipient)44 public ProfileAndCredentialEntry get(Recipient recipient) { 45 SignalServiceAddress address = recipient.getAddress(); 46 for (ProfileAndCredentialEntry entry : profiles) { 47 if (entry.getServiceAddress().matches(address)) { 48 return entry; 49 } 50 } 51 return null; 52 } 53 @JsonIgnore get(SignalServiceAddress address)54 public ProfileAndCredentialEntry get(SignalServiceAddress address) { 55 for (ProfileAndCredentialEntry entry : profiles) { 56 if (entry.getServiceAddress() == null) { 57 continue; 58 } 59 if (entry.getServiceAddress().matches(address)) { 60 return entry; 61 } 62 } 63 return null; 64 } 65 66 @JsonIgnore isUnsaved()67 public boolean isUnsaved() { 68 return unsaved; 69 } 70 markSaved()71 public void markSaved() { unsaved = false; } 72 storeProfileKey(Recipient recipient, ProfileKey profileKey)73 public ProfileAndCredentialEntry storeProfileKey(Recipient recipient, ProfileKey profileKey) { 74 ProfileAndCredentialEntry newEntry = new ProfileAndCredentialEntry(recipient.getAddress(), profileKey, 0, null, null, ProfileAndCredentialEntry.UnidentifiedAccessMode.UNKNOWN); 75 for (int i = 0; i < profiles.size(); i++) { 76 if (profiles.get(i).getServiceAddress().matches(recipient.getAddress())) { 77 if (!profiles.get(i).getProfileKey().equals(profileKey)) { 78 profiles.set(i, newEntry); 79 unsaved = true; 80 } 81 return newEntry; 82 } 83 } 84 profiles.add(newEntry); 85 unsaved = true; 86 return newEntry; 87 } 88 update(SignalServiceAddress address, ProfileKey profileKey, long now, SignalProfile profile, ProfileKeyCredential profileKeyCredential, ProfileAndCredentialEntry.UnidentifiedAccessMode unidentifiedAccessMode)89 public ProfileAndCredentialEntry update(SignalServiceAddress address, ProfileKey profileKey, long now, SignalProfile profile, ProfileKeyCredential profileKeyCredential, 90 ProfileAndCredentialEntry.UnidentifiedAccessMode unidentifiedAccessMode) { 91 ProfileAndCredentialEntry entry = new ProfileAndCredentialEntry(address, profileKey, now, profile, profileKeyCredential, unidentifiedAccessMode); 92 for (int i = 0; i < profiles.size(); i++) { 93 if (profiles.get(i).getServiceAddress().matches(address)) { 94 // TODO: announce profile change 95 profiles.set(i, entry); 96 unsaved = true; 97 return entry; 98 } 99 } 100 profiles.add(entry); 101 unsaved = true; 102 return entry; 103 } 104 } 105