package com.android.server.wifi.hotspot2;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
import static com.android.server.wifi.anqp.Constants.BYTE_MASK;
import static com.android.server.wifi.anqp.Constants.NIBBLE_MASK;
public abstract class Utils {
public static final long UNSET_TIME = -1;
private static final String[] PLMNText = {"org", "3gppnetwork", "mcc*", "mnc*", "wlan" };
public static String hs2LogTag(Class c) {
return "HS20";
}
public static List<String> splitDomain(String domain) {
if (domain.endsWith("."))
domain = domain.substring(0, domain.length() - 1);
int at = domain.indexOf('@');
if (at >= 0)
domain = domain.substring(at + 1);
String[] labels = domain.toLowerCase().split("\\.");
LinkedList<String> labelList = new LinkedList<String>();
for (String label : labels) {
labelList.addFirst(label);
}
return labelList;
}
public static long parseMac(String s) {
long mac = 0;
int count = 0;
for (int n = 0; n < s.length(); n++) {
int nibble = Utils.fromHex(s.charAt(n), true); // Set lenient to not blow up on ':'
if (nibble >= 0) { // ... and use only legit hex.
mac = (mac << 4) | nibble;
count++;
}
}
if (count < 12 || (count&1) == 1) {
throw new IllegalArgumentException("Bad MAC address: '" + s + "'");
}
return mac;
}
public static String getMccMnc(List<String> domain) {
if (domain.size() != PLMNText.length) {
return null;
}
for (int n = 0; n < PLMNText.length; n++ ) {
String expect = PLMNText[n];
int len = expect.endsWith("*") ? expect.length() - 1 : expect.length();
if (!domain.get(n).regionMatches(0, expect, 0, len)) {
return null;
}
}
String prefix = domain.get(2).substring(3) + domain.get(3).substring(3);
for (int n = 0; n < prefix.length(); n++) {
char ch = prefix.charAt(n);
if (ch < '0' || ch > '9') {
return null;
}
}
return prefix;
}
public static String roamingConsortiumsToString(long[] ois) {
if (ois == null) {
return "null";
}
List<Long> list = new ArrayList<Long>(ois.length);
for (long oi : ois) {
list.add(oi);
}
return roamingConsortiumsToString(list);
}
public static String roamingConsortiumsToString(Collection<Long> ois) {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (long oi : ois) {
if (first) {
first = false;
} else {
sb.append(", ");
}
if (Long.numberOfLeadingZeros(oi) > 40) {
sb.append(String.format("%06x", oi));
} else {
sb.append(String.format("%010x", oi));
}
}
return sb.toString();
}
public static String toUnicodeEscapedString(String s) {
StringBuilder sb = new StringBuilder(s.length());
for (int n = 0; n < s.length(); n++) {
char ch = s.charAt(n);
if (ch>= ' ' && ch < 127) {
sb.append(ch);
}
else {
sb.append("\\u").append(String.format("%04x", (int)ch));
}
}
return sb.toString();
}
public static String toHexString(byte[] data) {
if (data == null) {
return "null";
}
StringBuilder sb = new StringBuilder(data.length * 3);
boolean first = true;
for (byte b : data) {
if (first) {
first = false;
} else {
sb.append(' ');
}
sb.append(String.format("%02x", b & BYTE_MASK));
}
return sb.toString();
}
public static String toHex(byte[] octets) {
StringBuilder sb = new StringBuilder(octets.length * 2);
for (byte o : octets) {
sb.append(String.format("%02x", o & BYTE_MASK));
}
return sb.toString();
}
public static byte[] hexToBytes(String text) {
if ((text.length() & 1) == 1) {
throw new NumberFormatException("Odd length hex string: " + text.length());
}
byte[] data = new byte[text.length() >> 1];
int position = 0;
for (int n = 0; n < text.length(); n += 2) {
data[position] =
(byte) (((fromHex(text.charAt(n), false) & NIBBLE_MASK) << 4) |
(fromHex(text.charAt(n + 1), false) & NIBBLE_MASK));
position++;
}
return data;
}
public static int fromHex(char ch, boolean lenient) throws NumberFormatException {
if (ch <= '9' && ch >= '0') {
return ch - '0';
} else if (ch >= 'a' && ch <= 'f') {
return ch + 10 - 'a';
} else if (ch <= 'F' && ch >= 'A') {
return ch + 10 - 'A';
} else if (lenient) {
return -1;
} else {
throw new NumberFormatException("Bad hex-character: " + ch);
}
}
private static char toAscii(int b) {
return b >= ' ' && b < 0x7f ? (char) b : '.';
}
static boolean isDecimal(String s) {
for (int n = 0; n < s.length(); n++) {
char ch = s.charAt(n);
if (ch < '0' || ch > '9') {
return false;
}
}
return true;
}
public static <T extends Comparable> int compare(Comparable<T> c1, T c2) {
if (c1 == null) {
return c2 == null ? 0 : -1;
}
else if (c2 == null) {
return 1;
}
else {
return c1.compareTo(c2);
}
}
public static String bytesToBingoCard(ByteBuffer data, int len) {
ByteBuffer dup = data.duplicate();
dup.limit(dup.position() + len);
return bytesToBingoCard(dup);
}
public static String bytesToBingoCard(ByteBuffer data) {
ByteBuffer dup = data.duplicate();
StringBuilder sbx = new StringBuilder();
while (dup.hasRemaining()) {
sbx.append(String.format("%02x ", dup.get() & BYTE_MASK));
}
dup = data.duplicate();
sbx.append(' ');
while (dup.hasRemaining()) {
sbx.append(String.format("%c", toAscii(dup.get() & BYTE_MASK)));
}
return sbx.toString();
}
public static String toHMS(long millis) {
long time = millis >= 0 ? millis : -millis;
long tmp = time / 1000L;
long ms = time - tmp * 1000L;
time = tmp;
tmp /= 60L;
long s = time - tmp * 60L;
time = tmp;
tmp /= 60L;
long m = time - tmp * 60L;
return String.format("%s%d:%02d:%02d.%03d", millis < 0 ? "-" : "", tmp, m, s, ms);
}
public static String toUTCString(long ms) {
if (ms < 0) {
return "unset";
}
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c.setTimeInMillis(ms);
return String.format("%4d/%02d/%02d %2d:%02d:%02dZ",
c.get(Calendar.YEAR),
c.get(Calendar.MONTH) + 1,
c.get(Calendar.DAY_OF_MONTH),
c.get(Calendar.HOUR_OF_DAY),
c.get(Calendar.MINUTE),
c.get(Calendar.SECOND));
}
public static String unquote(String s) {
if (s == null) {
return null;
}
else if (s.startsWith("\"") && s.endsWith("\"")) {
return s.substring(1, s.length()-1);
}
else {
return s;
}
}
}