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

Last change on this file since 1431 was 1431, checked in by bln4, 5 years ago

Recoding of the Labels class to improve surrogate mode functionality. Surrogate mode is now maintained when you navigate from one frame to another, even if that frame has a different set of labels. Completely different sets of labels cause Expeditee to exit surrogate mode with a message to the user.

File size: 7.1 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 List<String> progressSurrogateMode(ItemsList context) {
41 // Maintain the local cache of user labels
42 ensureUserLabels();
43
44 List<String> ret;
45
46 List<String> localLabels = getLabelsFromContext(context);
47 if (userLabels.isEmpty() || localLabels.isEmpty()) {
48 // If either the labels in the context are empty or the user
49 // has no labels then we are not able to enter surrogate mode.
50 return userLabels;
51 }
52
53 ArrayList<String> intersection = new ArrayList<String>(userLabels);
54 intersection.retainAll(localLabels);
55 if (!isInSurrogateMode) {
56 isInSurrogateMode = true;
57 // Priming surrogate step to become zero in the loop below.
58 surrogateStep = -1;
59 }
60
61 // We are already in surrogate mode, progress it.
62 int index = surrogateStep + 1;
63 boolean found = false;
64 while (index < userLabels.size()) {
65 String surrogateMode = userLabels.get(index);
66 if (intersection.contains(surrogateMode)) {
67 found = true;
68 break;
69 }
70 index++;
71 }
72
73 if (found) {
74 isUnprivileged = false;
75 surrogateStep = index;
76 String chosenSurrogateMode = userLabels.get(surrogateStep);
77 ret = Arrays.asList(chosenSurrogateMode);
78 } else {
79 if (surrogateStep >= userLabels.size()) {
80 surrogateStep = 0;
81 isInSurrogateMode = false;
82 isUnprivileged = false;
83 ret = intersection;
84 } else {
85 ret = new ArrayList<String>();
86 surrogateStep = index;
87 isUnprivileged = true;
88 }
89 }
90
91 return ret;
92 }
93
94 public static void resetSurrogateMode() {
95 // Maintain the local cache of user labels
96 ensureUserLabels();
97
98 surrogateStep = 0;
99 isInSurrogateMode = false;
100 }
101
102 public static List<String> getAccessibleLabelsNames(ItemsList itemsList) {
103 // Maintain the local cache of user labels
104 ensureUserLabels();
105
106 if (isInSurrogateMode) {
107 if (isUnprivileged) {
108 return new ArrayList<String>();
109 } else {
110 return Arrays.asList(userLabels.get(surrogateStep));
111 }
112 } else {
113 return getLabelsFromContext(itemsList);
114 }
115 }
116
117 private static void ensureUserLabels() {
118 List<String> userSettingsLabelNames = KeyList.getLabelsNameOnly();
119 boolean hasNoKeys = userLabels.isEmpty() && userSettingsLabelNames.isEmpty();
120 boolean hasNotChanged = userLabels.equals(userSettingsLabelNames) || hasNoKeys;
121
122 if (hasNotChanged) { return; }
123
124 // Deal with the fact that the position of our current surrogate mode
125 // might have moved in the users list of labels.
126 if (userLabels.size() > surrogateStep) {
127 String surrogateMode = userLabels.get(surrogateStep);
128 int newIndexOfSurrogateMode = userSettingsLabelNames.indexOf(surrogateMode);
129 if (newIndexOfSurrogateMode >= 0) {
130 surrogateStep = newIndexOfSurrogateMode;
131 } else {
132 surrogateStep = 0;
133 isInSurrogateMode = false;
134 MessageBay.displayMessage("You have lost access to the encryption label "
135 + surrogateMode + ". Dropping out of surrogate mode.");
136 }
137 }
138
139 // (Re)Initialise the userLabels list and labelResultsCache.
140 userLabels.clear();
141 labelsInfo.clear();
142 Text[] userSettings = KeyList.UserLabels.get();
143 for (Text userSetting: userSettings) {
144 String labelName = userSetting.getName();
145 List<String> data = userSetting.getData();
146 if (data == null || data.isEmpty()) {
147 continue;
148 }
149
150 // Extract the data and check if we have a full or partial key.
151 String dataEntry = data.get(0);
152 if (dataEntry.contains("{")) {
153 userLabels.add(labelName);
154 LabelInfo labelInfo = new LabelInfo(LabelResult.SuccessResolveLabelToPartialKey, labelName, null);
155 labelsInfo.add(labelInfo);
156 } else {
157 userLabels.add(labelName);
158 byte[] key = Base64.getDecoder().decode(dataEntry);
159 LabelInfo labelInfo = new LabelInfo(LabelResult.SuccessResolveLabelToKey, labelName, key);
160 labelsInfo.add(labelInfo);
161 }
162 }
163 }
164
165 private static List<String> getLabelsFromContext(ItemsList context) {
166 Predicate<Item> hasEncryptionLabel = item -> item.getEncryptionLabel() != null && !item.getEncryptionLabel().isEmpty();
167 Collection<Item> local = new ItemsList(context).underlying();
168 Stream<Item> itemsWithLabel = local.stream().filter(hasEncryptionLabel);
169 Stream<String> labels = itemsWithLabel.map(item -> item.getEncryptionLabel()).distinct();
170 return labels.collect(Collectors.toList());
171 }
172
173 private static LabelInfo unableToFindLabelResult(String label) {
174 LabelInfo info = new LabelInfo(LabelResult.ErrorUnableToFindLabel, label, null);
175 return info;
176 }
177
178 public static class LabelInfo {
179
180 public byte[] key;
181 public String name;
182 public LabelResult type;
183
184 public LabelInfo(LabelResult type, String name, byte[] key) {
185 this.type = type;
186 this.name = name;
187 this.key = key;
188 }
189
190 public boolean is(LabelResult type) {
191 return this.type == type;
192 }
193
194 public String toString() {
195 switch(type) {
196 case SuccessResolveLabelToKey:
197 return "Resolved label to key: " + Base64.getEncoder().encodeToString(key);
198 case SuccessResolveLabelToPartialKey:
199 return "Resolved label to slice of a key: " + Base64.getEncoder().encodeToString(key);
200 case ErrorUnableToFindSecretsFrame:
201 return "Unable to find your Secrets Frame.";
202 case ErrorUnableToFindLabel:
203 return "Unable to resolve label to encrypt/decrypt frame. Label: " + name;
204 case ErrorForbiddenLabel:
205 return "Whilst you have the key for label " + name + " ; you are not allowed to use it.";
206 }
207
208 String message = "Was the list of possible enum results updated without nessasary changes to the toString() function?";
209 throw new IllegalArgumentException(message);
210 }
211 }
212
213 public enum LabelResult {
214 SuccessResolveLabelToKey,
215 SuccessResolveLabelToPartialKey,
216 ErrorUnableToFindSecretsFrame,
217 ErrorUnableToFindLabel,
218 ErrorForbiddenLabel;
219 }
220}
Note: See TracBrowser for help on using the repository browser.