source: trunk/src/org/expeditee/encryption/items/surrogates/Label.java@ 1443

Last change on this file since 1443 was 1443, checked in by bnemhaus, 5 years ago

Changed Label::progressSurrogate mode so that a null return values signifies that asking for surrogate mode makes no sense because there are no labels in play.

Fixed bug with DisplayController::toggleSurrogateMode. It was printing incorrect messages to the message bay when the user was supposed to be exiting surrogate mode. This was fixed by querying Label::isInSurrogateMode.

File size: 7.7 KB
Line 
1package org.expeditee.encryption.items.surrogates;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.Base64;
6import java.util.Collection;
7import java.util.List;
8import java.util.function.Predicate;
9import java.util.stream.Collectors;
10import java.util.stream.Stream;
11
12import org.expeditee.gui.ItemsList;
13import org.expeditee.gui.MessageBay;
14import org.expeditee.items.Item;
15import org.expeditee.items.Text;
16import org.expeditee.settings.identity.secrets.KeyList;
17
18public class Label {
19 private static List<String> userLabels = new ArrayList<String>();
20 private static List<LabelInfo> labelsInfo = new ArrayList<LabelInfo>();
21 private static int surrogateStep = 0;
22 private static boolean isInSurrogateMode = false;
23 private static boolean isUnprivileged = false;
24
25 public static LabelInfo getLabel(String labelName) {
26 // Maintain the local cache of user labels
27 ensureUserLabels();
28
29 int indexOfLabel = userLabels.indexOf(labelName);
30 if (indexOfLabel == -1) {
31 //A label by the specified name does not exist.
32 return unableToFindLabelResult(labelName);
33 } else {
34 //A label by the specified name is in the local cache and can be used.
35 LabelInfo labelResult = labelsInfo.get(indexOfLabel);
36 return labelResult;
37 }
38 }
39
40 public static boolean isInSurrogateMode() {
41 return isInSurrogateMode;
42 }
43
44 /**
45 * Progresses surrogate mode and returns a list of labels that are currently in effect.
46 * @param context The list of expeditee Items to be considered for context. These are checked for labels.
47 * @return Returns either:
48 * <ol type='a'>
49 * <li> A list of length 1 specifying the label that the current surrogate mode accepts or </li>
50 * <li> A list of length 0 which specifies that surrogate mode is in unprivileged view or </li>
51 * <li> Null, which means there are no labels in play on this frame
52 * (so asking for surrogate mode does not make sense) </li>
53 * </ol>
54 */
55 public static List<String> progressSurrogateMode(ItemsList context) {
56 // Maintain the local cache of user labels
57 ensureUserLabels();
58
59 List<String> ret;
60
61 List<String> localLabels = getLabelsFromContext(context);
62 if (localLabels.isEmpty()) {
63 // If there are no labels on this Frame return null;
64 return null;
65 }
66
67 ArrayList<String> intersection = new ArrayList<String>(userLabels);
68 intersection.retainAll(localLabels);
69 if (!isInSurrogateMode) {
70 isInSurrogateMode = true;
71 // Priming surrogate step to become zero in the loop below.
72 surrogateStep = -1;
73 }
74
75 // We are already in surrogate mode, progress it.
76 int index = surrogateStep + 1;
77 boolean found = false;
78 while (index < userLabels.size()) {
79 String surrogateMode = userLabels.get(index);
80 if (intersection.contains(surrogateMode)) {
81 found = true;
82 break;
83 }
84 index++;
85 }
86
87 if (found) {
88 isUnprivileged = false;
89 surrogateStep = index;
90 String chosenSurrogateMode = userLabels.get(surrogateStep);
91 ret = Arrays.asList(chosenSurrogateMode);
92 } else {
93 if (surrogateStep >= userLabels.size()) {
94 surrogateStep = 0;
95 isInSurrogateMode = false;
96 isUnprivileged = false;
97 ret = intersection;
98 } else {
99 ret = new ArrayList<String>();
100 surrogateStep = index;
101 isUnprivileged = true;
102 }
103 }
104
105 return ret;
106 }
107
108 public static void resetSurrogateMode() {
109 // Maintain the local cache of user labels
110 ensureUserLabels();
111
112 surrogateStep = 0;
113 isInSurrogateMode = false;
114 }
115
116 public static List<String> getAccessibleLabelsNames(ItemsList itemsList) {
117 // Maintain the local cache of user labels
118 ensureUserLabels();
119
120 if (isInSurrogateMode) {
121 if (isUnprivileged) {
122 return new ArrayList<String>();
123 } else {
124 return Arrays.asList(userLabels.get(surrogateStep));
125 }
126 } else {
127 return getLabelsFromContext(itemsList);
128 }
129 }
130
131 private static void ensureUserLabels() {
132 List<String> userSettingsLabelNames = KeyList.getLabelsNameOnly();
133 boolean hasNoKeys = userLabels.isEmpty() && userSettingsLabelNames.isEmpty();
134 boolean hasNotChanged = userLabels.equals(userSettingsLabelNames) || hasNoKeys;
135
136 if (hasNotChanged) { return; }
137
138 // Deal with the fact that the position of our current surrogate mode
139 // might have moved in the users list of labels.
140 if (userLabels.size() > surrogateStep) {
141 String surrogateMode = userLabels.get(surrogateStep);
142 int newIndexOfSurrogateMode = userSettingsLabelNames.indexOf(surrogateMode);
143 if (newIndexOfSurrogateMode >= 0) {
144 surrogateStep = newIndexOfSurrogateMode;
145 } else {
146 surrogateStep = 0;
147 isInSurrogateMode = false;
148 MessageBay.displayMessage("You have lost access to the encryption label "
149 + surrogateMode + ". Dropping out of surrogate mode.");
150 }
151 }
152
153 // (Re)Initialise the userLabels list and labelResultsCache.
154 userLabels.clear();
155 labelsInfo.clear();
156 Text[] userSettings = KeyList.UserLabels.get();
157 for (Text userSetting: userSettings) {
158 String labelName = userSetting.getName();
159 List<String> data = userSetting.getData();
160 if (data == null || data.isEmpty()) {
161 continue;
162 }
163
164 // Extract the data and check if we have a full or partial key.
165 String dataEntry = data.get(0);
166 if (dataEntry.contains("{")) {
167 userLabels.add(labelName);
168 LabelInfo labelInfo = new LabelInfo(LabelResult.SuccessResolveLabelToPartialKey, labelName, null);
169 labelsInfo.add(labelInfo);
170 } else {
171 userLabels.add(labelName);
172 byte[] key = Base64.getDecoder().decode(dataEntry);
173 LabelInfo labelInfo = new LabelInfo(LabelResult.SuccessResolveLabelToKey, labelName, key);
174 labelsInfo.add(labelInfo);
175 }
176 }
177 }
178
179 private static List<String> getLabelsFromContext(ItemsList context) {
180 Predicate<Item> hasEncryptionLabel = item -> item.getEncryptionLabel() != null && !item.getEncryptionLabel().isEmpty();
181 Collection<Item> local = new ItemsList(context).underlying();
182 Stream<Item> itemsWithLabel = local.stream().filter(hasEncryptionLabel);
183 Stream<String> labels = itemsWithLabel.map(item -> item.getEncryptionLabel()).distinct();
184 return labels.collect(Collectors.toList());
185 }
186
187 private static LabelInfo unableToFindLabelResult(String label) {
188 LabelInfo info = new LabelInfo(LabelResult.ErrorUnableToFindLabel, label, null);
189 return info;
190 }
191
192 public static class LabelInfo {
193
194 public byte[] key;
195 public String name;
196 public LabelResult type;
197
198 public LabelInfo(LabelResult type, String name, byte[] key) {
199 this.type = type;
200 this.name = name;
201 this.key = key;
202 }
203
204 public boolean is(LabelResult type) {
205 return this.type == type;
206 }
207
208 public String toString() {
209 switch(type) {
210 case SuccessResolveLabelToKey:
211 return "Resolved label to key: " + Base64.getEncoder().encodeToString(key);
212 case SuccessResolveLabelToPartialKey:
213 return "Resolved label to slice of a key: " + Base64.getEncoder().encodeToString(key);
214 case ErrorUnableToFindSecretsFrame:
215 return "Unable to find your Secrets Frame.";
216 case ErrorUnableToFindLabel:
217 return "Unable to resolve label to encrypt/decrypt frame. Label: " + name;
218 case ErrorForbiddenLabel:
219 return "Whilst you have the key for label " + name + " ; you are not allowed to use it.";
220 }
221
222 String message = "Was the list of possible enum results updated without nessasary changes to the toString() function?";
223 throw new IllegalArgumentException(message);
224 }
225 }
226
227 public enum LabelResult {
228 SuccessResolveLabelToKey,
229 SuccessResolveLabelToPartialKey,
230 ErrorUnableToFindSecretsFrame,
231 ErrorUnableToFindLabel,
232 ErrorForbiddenLabel;
233 }
234}
Note: See TracBrowser for help on using the repository browser.