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.JsonProperty;
21 import io.finn.signald.clientprotocol.v1.JsonAddress;
22 import io.finn.signald.db.Recipient;
23 import io.finn.signald.util.AddressUtil;
24 import java.util.ArrayList;
25 import java.util.List;
26 import org.whispersystems.signalservice.api.messages.multidevice.DeviceContact;
27 import org.whispersystems.util.Base64;
28 
29 public class ContactStore {
30   public List<ContactInfo> contacts = new ArrayList<>();
31 
updateContact(ContactInfo contact)32   public ContactInfo updateContact(ContactInfo contact) {
33     synchronized (contacts) {
34       for (ContactInfo c : contacts) {
35         if (c.address.matches(contact.address)) {
36           c.update(contact);
37           return c;
38         }
39       }
40       contacts.add(contact);
41     }
42     return contact;
43   }
44 
getContact(Recipient recipient)45   public ContactInfo getContact(Recipient recipient) {
46     synchronized (contacts) {
47       for (ContactInfo c : contacts) {
48         if (c.matches(recipient)) {
49           return c;
50         }
51       }
52     }
53     return new ContactInfo(recipient);
54   }
55 
getContacts()56   public List<ContactInfo> getContacts() {
57     synchronized (contacts) { return contacts; }
58   }
59 
clear()60   public void clear() {
61     synchronized (contacts) { contacts.clear(); }
62   }
63 
64   public static class ContactInfo {
65     @JsonProperty public String name;
66 
67     @JsonProperty public JsonAddress address;
68 
69     @JsonProperty public String color;
70 
71     @JsonProperty public String profileKey;
72 
73     @JsonProperty public int messageExpirationTime;
74 
75     public Integer inboxPosition;
76 
ContactInfo()77     public ContactInfo() {}
78 
ContactInfo(Recipient recipient)79     public ContactInfo(Recipient recipient) { address = new JsonAddress(recipient.getAddress()); }
80 
setNumber(@sonProperty String number)81     public void setNumber(@JsonProperty String number) {
82       if (address == null) {
83         address = new JsonAddress(number);
84       } else {
85         address.number = number;
86       }
87     }
88 
setIdentifier(@sonProperty String identifier)89     public void setIdentifier(@JsonProperty String identifier) {
90       if (address == null) {
91         address = new JsonAddress(AddressUtil.fromIdentifier(identifier));
92       } else {
93         address.uuid = identifier;
94       }
95     }
96 
update(ContactInfo other)97     public void update(ContactInfo other) {
98       address = AddressUtil.update(address, other.address);
99       messageExpirationTime = other.messageExpirationTime;
100       if (other.name != null) {
101         name = other.name;
102       }
103       if (other.color != null) {
104         color = other.color;
105       }
106       if (other.profileKey != null) {
107         profileKey = other.profileKey;
108       }
109 
110       if (other.inboxPosition != null) {
111         inboxPosition = other.inboxPosition;
112       }
113     }
114 
matches(Recipient other)115     public boolean matches(Recipient other) { return address.matches(other.getAddress()); }
116 
update(DeviceContact c)117     public void update(DeviceContact c) {
118       address = new JsonAddress(c.getAddress());
119 
120       if (c.getName().isPresent()) {
121         name = c.getName().get();
122       }
123 
124       if (c.getColor().isPresent()) {
125         color = c.getColor().get();
126       }
127 
128       if (c.getProfileKey().isPresent()) {
129         profileKey = Base64.encodeBytes(c.getProfileKey().get().serialize());
130       }
131 
132       if (c.getExpirationTimer().isPresent()) {
133         messageExpirationTime = c.getExpirationTimer().get();
134       }
135 
136       if (c.getInboxPosition().isPresent()) {
137         inboxPosition = c.getInboxPosition().get();
138       }
139     }
140 
setVerified(JsonVerifiedState v)141     public void setVerified(JsonVerifiedState v) {}
142   }
143 }
144