2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.anel.internal.auth;
15 import java.util.Base64;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
23 * This class determines the authentication method from a status response of an ANEL device.
25 * @author Patrick Koenemann - Initial contribution
28 public class AnelAuthentication {
30 public enum AuthMethod {
35 private static final Pattern NAME_AND_FIRMWARE_PATTERN = Pattern.compile(":NET-PWRCTRL_0?(\\d+\\.\\d)");
36 private static final Pattern LAST_SEGMENT_FIRMWARE_PATTERN = Pattern.compile(":(\\d+\\.\\d)$");
38 private static final String MIN_FIRMWARE_BASE64 = "6.0";
39 private static final String MIN_FIRMWARE_XOR_BASE64 = "6.1";
41 public static AuthMethod of(String status) {
42 if (status.isEmpty()) {
43 return PLAIN; // fallback
45 if (status.trim().endsWith(":xor") || status.contains(":xor:")) {
48 final String firmwareVersion = getFirmwareVersion(status);
49 if (firmwareVersion == null) {
52 if (firmwareVersion.compareTo(MIN_FIRMWARE_XOR_BASE64) >= 0) {
53 return XORBASE64; // >= 6.1
55 if (firmwareVersion.compareTo(MIN_FIRMWARE_BASE64) >= 0) {
56 return BASE64; // exactly 6.0
58 return PLAIN; // fallback
61 private static @Nullable String getFirmwareVersion(String fullStatusStringOrFirmwareVersion) {
62 final Matcher matcher1 = NAME_AND_FIRMWARE_PATTERN.matcher(fullStatusStringOrFirmwareVersion);
63 if (matcher1.find()) {
64 return matcher1.group(1);
66 final Matcher matcher2 = LAST_SEGMENT_FIRMWARE_PATTERN.matcher(fullStatusStringOrFirmwareVersion.trim());
67 if (matcher2.find()) {
68 return matcher2.group(1);
74 public static String getUserPasswordString(@Nullable String user, @Nullable String password,
75 @Nullable AuthMethod authMethod) {
76 final String userPassword = (user == null ? "" : user) + (password == null ? "" : password);
77 if (authMethod == null || authMethod == AuthMethod.PLAIN) {
81 if (authMethod == AuthMethod.BASE64 || password == null || password.isEmpty()) {
82 return Base64.getEncoder().encodeToString(userPassword.getBytes());
85 if (authMethod == AuthMethod.XORBASE64) {
86 final StringBuilder result = new StringBuilder();
89 for (int c = 0; c < userPassword.length(); c++) {
90 result.append((char) (userPassword.charAt(c) ^ password.charAt(c % password.length())));
93 return Base64.getEncoder().encodeToString(result.toString().getBytes());
96 throw new UnsupportedOperationException("Unknown auth method: " + authMethod);