WifiSsid.java revision b6deeed3ceff9e0f754697987b7c724901996082
1b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff/*
2b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * Copyright (C) 2012 The Android Open Source Project
3b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff *
4b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License");
5b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * you may not use this file except in compliance with the License.
6b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * You may obtain a copy of the License at
7b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff *
8b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff *      http://www.apache.org/licenses/LICENSE-2.0
9b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff *
10b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * Unless required by applicable law or agreed to in writing, software
11b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS,
12b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * See the License for the specific language governing permissions and
14b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * limitations under the License.
15b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff */
16b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
17b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffpackage android.net.wifi;
18b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
19b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport android.os.Parcelable;
20b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport android.os.Parcel;
21b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport android.util.Log;
22b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
23b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.io.ByteArrayOutputStream;
24b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.nio.ByteBuffer;
25b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.nio.CharBuffer;
26b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.nio.charset.Charset;
27b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.nio.charset.CharsetDecoder;
28b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.nio.charset.CoderResult;
29b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffimport java.nio.charset.CodingErrorAction;
30b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
31b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff/**
32b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * Stores SSID octets and handles conversion.
33b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff *
34b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * For Ascii encoded string, any octet < 32 or > 127 is encoded as
35b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * a "\x" followed by the hex representation of the octet.
36b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * Exception chars are ", \, \e, \n, \r, \t which are escaped by a \
37b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * See src/utils/common.c for the implementation in the supplicant.
38b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff *
39b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff * @hide
40b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff */
41b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriffpublic class WifiSsid implements Parcelable {
42b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    private static final String TAG = "WifiSsid";
43b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
44b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public ByteArrayOutputStream octets = new ByteArrayOutputStream(32);
45b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
46b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    private static final int HEX_RADIX = 16;
47b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public static final String NONE = "<unknown ssid>";
48b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
49b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    private WifiSsid() {
50b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
51b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
52b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public static WifiSsid createFromAsciiEncoded(String asciiEncoded) {
53b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        WifiSsid a = new WifiSsid();
54b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        a.convertToBytes(asciiEncoded);
55b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return a;
56b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
57b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
58b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public static WifiSsid createFromHex(String hexStr) {
59b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        WifiSsid a = new WifiSsid();
60b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        int length = 0;
61b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        if (hexStr == null) return a;
62b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
63b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        if (hexStr.startsWith("0x") || hexStr.startsWith("0X")) {
64b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            hexStr = hexStr.substring(2);
65b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
66b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
67b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        for (int i = 0; i < hexStr.length()-1; i += 2) {
68b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            int val;
69b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            try {
70b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                val = Integer.parseInt(hexStr.substring(i, i + 2), HEX_RADIX);
71b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            } catch(NumberFormatException e) {
72b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                val = 0;
73b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            }
74b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            a.octets.write(val);
75b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
76b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return a;
77b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
78b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
79b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /* This function is equivalent to printf_decode() at src/utils/common.c in
80b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff     * the supplicant */
81b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    private void convertToBytes(String asciiEncoded) {
82b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        int i = 0;
83b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        int val = 0;
84b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        while (i< asciiEncoded.length()) {
85b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            char c = asciiEncoded.charAt(i);
86b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            switch (c) {
87b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                case '\\':
88b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    i++;
89b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    switch(asciiEncoded.charAt(i)) {
90b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '\\':
91b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write('\\');
92b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
93b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '"':
94b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write('"');
95b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
96b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case 'n':
97b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write('\n');
98b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
99b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case 'r':
100b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write('\r');
101b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
102b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case 't':
103b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write('\t');
104b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
105b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case 'e':
106b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write(27); //escape char
107b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
108b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case 'x':
109b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            i++;
110b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            try {
111b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                val = Integer.parseInt(asciiEncoded.substring(i, i + 2), HEX_RADIX);
112b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            } catch (NumberFormatException e) {
113b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                val = -1;
114b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            }
115b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            if (val < 0) {
116b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                val = Character.digit(asciiEncoded.charAt(i), HEX_RADIX);
117b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                if (val < 0) break;
118b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                octets.write(val);
119b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                i++;
120b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            } else {
121b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                octets.write(val);
122b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                i += 2;
123b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            }
124b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
125b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '0':
126b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '1':
127b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '2':
128b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '3':
129b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '4':
130b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '5':
131b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '6':
132b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        case '7':
133b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            val = asciiEncoded.charAt(i) - '0';
134b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            i++;
135b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') {
136b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                val = val * 8 + asciiEncoded.charAt(i) - '0';
137b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                i++;
138b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            }
139b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') {
140b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                val = val * 8 + asciiEncoded.charAt(i) - '0';
141b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                                i++;
142b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            }
143b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            octets.write(val);
144b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
145b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                        default:
146b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                            break;
147b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    }
148b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    break;
149b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                default:
150b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    octets.write(c);
151b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    i++;
152b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                    break;
153b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            }
154b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
155b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
156b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
157b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    @Override
158b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public String toString() {
159b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        if (octets.size() <= 0) return "";
160b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        // TODO: Handle conversion to other charsets upon failure
161b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        Charset charset = Charset.forName("UTF-8");
162b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        CharsetDecoder decoder = charset.newDecoder()
163b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                .onMalformedInput(CodingErrorAction.REPLACE)
164b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                .onUnmappableCharacter(CodingErrorAction.REPLACE);
165b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        CharBuffer out = CharBuffer.allocate(32);
166b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
167b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        CoderResult result = decoder.decode(ByteBuffer.wrap(octets.toByteArray()), out, true);
168b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        out.flip();
169b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        if (result.isError()) {
170b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            return NONE;
171b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
172b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return out.toString();
173b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
174b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
175b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** @hide */
176b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public byte[] getOctets() {
177b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return  octets.toByteArray();
178b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
179b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
180b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** @hide */
181b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public String getHexString() {
182b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        String out = "0x";
183b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        byte[] ssidbytes = getOctets();
184b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        for (int i = 0; i < octets.size(); i++) {
185b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            out += String.format("%02x", ssidbytes[i]);
186b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
187b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return out;
188b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
189b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
190b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
191b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public int describeContents() {
192b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return 0;
193b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
194b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
195b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
196b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public void writeToParcel(Parcel dest, int flags) {
197b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        dest.writeInt(octets.size());
198b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        dest.writeByteArray(octets.toByteArray());
199b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
200b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
201b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
202b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public static final Creator<WifiSsid> CREATOR =
203b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        new Creator<WifiSsid>() {
204b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            public WifiSsid createFromParcel(Parcel in) {
205b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                WifiSsid ssid = new WifiSsid();
206b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                int length = in.readInt();
207b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                byte b[] = new byte[length];
208b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                in.readByteArray(b);
209b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                ssid.octets.write(b, 0, length);
210b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                return ssid;
211b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            }
212b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
213b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            public WifiSsid[] newArray(int size) {
214b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                return new WifiSsid[size];
215b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            }
216b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        };
217b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff}
218