WifiSsid.java revision 462ff630e441f5bc36c4b926ce81bdb35fe7d04b
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() {
159462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        byte[] ssidBytes = octets.toByteArray();
160462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        // Supplicant returns \x00\x00\x00\x00\x00\x00\x00\x00 hex string
161462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        // for a hidden access point. Make sure we maintain the previous
162462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        // behavior of returning empty string for this case.
163462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        if (octets.size() <= 0 || isArrayAllZeroes(ssidBytes)) return "";
164b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        // TODO: Handle conversion to other charsets upon failure
165b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        Charset charset = Charset.forName("UTF-8");
166b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        CharsetDecoder decoder = charset.newDecoder()
167b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                .onMalformedInput(CodingErrorAction.REPLACE)
168b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                .onUnmappableCharacter(CodingErrorAction.REPLACE);
169b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        CharBuffer out = CharBuffer.allocate(32);
170b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
171462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        CoderResult result = decoder.decode(ByteBuffer.wrap(ssidBytes), out, true);
172b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        out.flip();
173b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        if (result.isError()) {
174b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            return NONE;
175b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
176b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return out.toString();
177b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
178b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
179462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff    private boolean isArrayAllZeroes(byte[] ssidBytes) {
180462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        for (int i = 0; i< ssidBytes.length; i++) {
181462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff            if (ssidBytes[i] != 0) return false;
182462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        }
183462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff        return true;
184462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff    }
185462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff
186b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** @hide */
187b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public byte[] getOctets() {
188b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return  octets.toByteArray();
189b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
190b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
191b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** @hide */
192b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public String getHexString() {
193b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        String out = "0x";
194b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        byte[] ssidbytes = getOctets();
195b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        for (int i = 0; i < octets.size(); i++) {
196b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            out += String.format("%02x", ssidbytes[i]);
197b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        }
198b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return out;
199b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
200b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
201b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
202b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public int describeContents() {
203b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        return 0;
204b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
205b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
206b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
207b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public void writeToParcel(Parcel dest, int flags) {
208b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        dest.writeInt(octets.size());
209b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        dest.writeByteArray(octets.toByteArray());
210b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    }
211b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
212b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    /** Implement the Parcelable interface {@hide} */
213b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff    public static final Creator<WifiSsid> CREATOR =
214b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        new Creator<WifiSsid>() {
215b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            public WifiSsid createFromParcel(Parcel in) {
216b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                WifiSsid ssid = new WifiSsid();
217b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                int length = in.readInt();
218b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                byte b[] = new byte[length];
219b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                in.readByteArray(b);
220b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                ssid.octets.write(b, 0, length);
221b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                return ssid;
222b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            }
223b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff
224b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            public WifiSsid[] newArray(int size) {
225b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff                return new WifiSsid[size];
226b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff            }
227b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff        };
228b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff}
229