]> git.basschouten.com Git - openhab-addons.git/blob
d6ce50c9c756641d4def0775348f791352cec2c7
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.mybmw.internal.handler.backend;
14
15 import java.util.regex.Pattern;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19
20 /**
21  *
22  * anonymizes all occurrencies of locations and vins
23  *
24  * @author Bernd Weymann - Initial contribution
25  * @author Martin Grassl - refactoring & extension for any occurrence
26  * @author Mark Herwege - extended log anonymization
27  */
28 @NonNullByDefault
29 public interface ResponseContentAnonymizer {
30
31     static final String ANONYMOUS_VIN = "anonymousVin";
32     static final String VIN_PATTERN = "\"vin\":";
33     static final String VEHICLE_CHARGING_LOCATION_PATTERN = "\"subtitle\":";
34     static final String VEHICLE_LOCATION_PATTERN = "\"location\":";
35     static final String VEHICLE_LOCATION_LATITUDE_PATTERN = "latitude";
36     static final String VEHICLE_LOCATION_LONGITUDE_PATTERN = "longitude";
37     static final String VEHICLE_LOCATION_FORMATTED_PATTERN = "formatted";
38     static final String VEHICLE_LOCATION_HEADING_PATTERN = "heading";
39     static final String VEHICLE_LOCATION_LATITUDE = "1.1";
40     static final String VEHICLE_LOCATION_LONGITUDE = "2.2";
41     static final String ANONYMOUS_ADDRESS = "anonymousAddress";
42     static final String VEHICLE_LOCATION_HEADING = "-1";
43     static final String RAW_VEHICLE_LOCATION_PATTERN_START = "\\\"location\\\"";
44     static final String RAW_VEHICLE_LOCATION_PATTERN_END = "\\\"heading\\\"";
45     static final String RAW_VEHICLE_LOCATION_PATTERN_REPLACER = "\"location\":{\"coordinates\":{\"latitude\":"
46             + VEHICLE_LOCATION_LATITUDE + ",\"longitude\":" + VEHICLE_LOCATION_LONGITUDE
47             + "},\"address\":{\"formatted\":\"" + ANONYMOUS_ADDRESS + "\"},";
48
49     static final String CLOSING_BRACKET = "}";
50     static final String QUOTE = "\"";
51     static final String CLOSE_VALUE = "\":";
52     static final String COMMA = ",";
53
54     /**
55      * anonymizes the responseContent
56      * <p>
57      * - vin
58      * </p>
59      * <p>
60      * - location
61      * </p>
62      *
63      * @param responseContent
64      * @return
65      */
66     public static String anonymizeResponseContent(@Nullable String responseContent) {
67         if (responseContent == null) {
68             return "";
69         }
70
71         String anonymizedVinString = replaceVins(responseContent);
72
73         String anonymizedLocationString = replaceLocations(anonymizedVinString);
74
75         String anonymizedRawLocationString = replaceRawLocations(anonymizedLocationString);
76
77         String anonymizedChargingLocationString = replaceChargingLocations(anonymizedRawLocationString);
78
79         return anonymizedChargingLocationString;
80     }
81
82     static String replaceChargingLocations(String stringToBeReplaced) {
83         String[] locationStrings = stringToBeReplaced.split(VEHICLE_CHARGING_LOCATION_PATTERN);
84
85         StringBuffer replacedString = new StringBuffer();
86         replacedString.append(locationStrings[0]);
87         for (int i = 1; locationStrings.length > 0 && i < locationStrings.length && locationStrings[i] != null; i++) {
88             replacedString.append(VEHICLE_CHARGING_LOCATION_PATTERN);
89             replacedString.append(replaceChargingLocation(locationStrings[i]));
90         }
91
92         return replacedString.toString();
93     }
94
95     static String replaceChargingLocation(String responseContent) {
96         String[] subtitleStrings = responseContent.split(" • ", 2);
97
98         StringBuffer replacedString = new StringBuffer();
99
100         replacedString.append("\"");
101         replacedString.append(ANONYMOUS_ADDRESS);
102         if (subtitleStrings.length > 1) {
103             replacedString.append(" • ");
104             replacedString.append(subtitleStrings[1]);
105         }
106
107         return replacedString.toString();
108     }
109
110     static String replaceRawLocations(String stringToBeReplaced) {
111         String[] locationStrings = stringToBeReplaced.split(Pattern.quote(RAW_VEHICLE_LOCATION_PATTERN_START));
112
113         StringBuffer replacedString = new StringBuffer();
114         replacedString.append(locationStrings[0]);
115         for (int i = 1; locationStrings.length > 0 && i < locationStrings.length && locationStrings[i] != null; i++) {
116             replacedString.append(replaceRawLocation(locationStrings[i]));
117         }
118
119         return replacedString.toString();
120     }
121
122     /**
123      * this just replaces a string
124      *
125      * @param string
126      * @return
127      */
128     static String replaceRawLocation(String stringToBeReplaced) {
129         String[] stringParts = stringToBeReplaced.split(Pattern.quote(RAW_VEHICLE_LOCATION_PATTERN_END));
130
131         StringBuffer replacedString = new StringBuffer();
132         replacedString.append(RAW_VEHICLE_LOCATION_PATTERN_REPLACER);
133         replacedString.append(RAW_VEHICLE_LOCATION_PATTERN_END);
134         replacedString.append(stringParts[1]);
135         return replacedString.toString();
136     }
137
138     static String replaceLocations(String stringToBeReplaced) {
139         String[] locationStrings = stringToBeReplaced.split(VEHICLE_LOCATION_PATTERN);
140
141         StringBuffer replacedString = new StringBuffer();
142         replacedString.append(locationStrings[0]);
143         for (int i = 1; locationStrings.length > 0 && i < locationStrings.length && locationStrings[i] != null; i++) {
144             replacedString.append(VEHICLE_LOCATION_PATTERN);
145             replacedString.append(replaceLocation(locationStrings[i]));
146         }
147
148         return replacedString.toString();
149     }
150
151     static String replaceLocation(String responseContent) {
152         String stringToBeReplaced = responseContent;
153
154         StringBuffer replacedString = new StringBuffer();
155         // latitude
156         stringToBeReplaced = replaceNumberValue(stringToBeReplaced, replacedString, VEHICLE_LOCATION_LATITUDE_PATTERN,
157                 VEHICLE_LOCATION_LATITUDE);
158
159         // longitude
160         stringToBeReplaced = replaceNumberValue(stringToBeReplaced, replacedString, VEHICLE_LOCATION_LONGITUDE_PATTERN,
161                 VEHICLE_LOCATION_LONGITUDE);
162
163         // formatted address
164         stringToBeReplaced = replaceStringValue(stringToBeReplaced, replacedString, VEHICLE_LOCATION_FORMATTED_PATTERN,
165                 ANONYMOUS_ADDRESS);
166
167         // heading
168         stringToBeReplaced = replaceNumberValue(stringToBeReplaced, replacedString, VEHICLE_LOCATION_HEADING_PATTERN,
169                 VEHICLE_LOCATION_HEADING);
170
171         replacedString.append(stringToBeReplaced);
172
173         return replacedString.toString();
174     }
175
176     static String replaceNumberValue(String stringToBeReplaced, StringBuffer replacedString, String replacerPattern,
177             String replacerValue) {
178         int startIndex = stringToBeReplaced.indexOf(replacerPattern, 1)
179                 + (replacerPattern.length() + CLOSE_VALUE.length());
180         int endIndex = -1;
181
182         // in an object, the comma comes after the value or a closing bracket
183         if (stringToBeReplaced.indexOf(COMMA, startIndex) < stringToBeReplaced.indexOf(CLOSING_BRACKET, startIndex)) {
184             endIndex = stringToBeReplaced.indexOf(COMMA, startIndex);
185         } else {
186             endIndex = stringToBeReplaced.indexOf(CLOSING_BRACKET, startIndex);
187         }
188
189         replacedString.append(stringToBeReplaced.substring(0, startIndex));
190         replacedString.append(replacerValue);
191
192         return stringToBeReplaced.substring(endIndex);
193     }
194
195     static String replaceStringValue(String stringToBeReplaced, StringBuffer replacedString, String replacerPattern,
196             String replacerValue) {
197         // the startIndex is the String after the first quote of the value after the key
198         // detect end of key
199         int startIndex = stringToBeReplaced.indexOf(replacerPattern, 1)
200                 + (replacerPattern.length() + CLOSE_VALUE.length());
201         // detect start of value
202         startIndex = stringToBeReplaced.indexOf(QUOTE, startIndex) + 1;
203
204         // detect end of value
205         int endIndex = stringToBeReplaced.indexOf(QUOTE, startIndex);
206
207         replacedString.append(stringToBeReplaced.substring(0, startIndex));
208         replacedString.append(replacerValue);
209
210         return stringToBeReplaced.substring(endIndex);
211     }
212
213     static String replaceVins(String stringToBeReplaced) {
214         String[] vinStrings = stringToBeReplaced.split(VIN_PATTERN);
215
216         StringBuffer replacedString = new StringBuffer();
217         replacedString.append(vinStrings[0]);
218         for (int i = 1; vinStrings.length > 0 && i < vinStrings.length; i++) {
219             replacedString.append(VIN_PATTERN);
220             replacedString.append(replaceVin(vinStrings[i]));
221         }
222
223         return replacedString.toString();
224     }
225
226     static String replaceVin(String stringToBeReplaced) {
227         // the vin is between two quotes
228         int startIndex = stringToBeReplaced.indexOf(QUOTE) + 1;
229         int endIndex = stringToBeReplaced.indexOf(QUOTE, startIndex);
230
231         StringBuffer replacedString = new StringBuffer();
232         replacedString.append(stringToBeReplaced.substring(0, startIndex));
233         replacedString.append(ANONYMOUS_VIN);
234         replacedString.append(stringToBeReplaced.substring(endIndex));
235
236         return replacedString.toString();
237     }
238
239     static @Nullable String replaceVin(@Nullable String stringToBeReplaced, @Nullable String vin) {
240         if (stringToBeReplaced == null) {
241             return null;
242         }
243         return vin != null ? stringToBeReplaced.replace(vin, ANONYMOUS_VIN) : stringToBeReplaced;
244     }
245 }