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('\\'); 9211de9e5537914bbe140fd99ad55333e48a14a667Irfan Sheriff i++; 93b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 94b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '"': 95b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write('"'); 9611de9e5537914bbe140fd99ad55333e48a14a667Irfan Sheriff i++; 97b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 98b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case 'n': 99b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write('\n'); 10011de9e5537914bbe140fd99ad55333e48a14a667Irfan Sheriff i++; 101b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 102b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case 'r': 103b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write('\r'); 10411de9e5537914bbe140fd99ad55333e48a14a667Irfan Sheriff i++; 105b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 106b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case 't': 107b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write('\t'); 10811de9e5537914bbe140fd99ad55333e48a14a667Irfan Sheriff i++; 109b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 110b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case 'e': 111b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write(27); //escape char 11211de9e5537914bbe140fd99ad55333e48a14a667Irfan Sheriff i++; 113b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 114b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case 'x': 115b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i++; 116b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff try { 117b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff val = Integer.parseInt(asciiEncoded.substring(i, i + 2), HEX_RADIX); 118b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } catch (NumberFormatException e) { 119b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff val = -1; 120b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 121b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff if (val < 0) { 122b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff val = Character.digit(asciiEncoded.charAt(i), HEX_RADIX); 123b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff if (val < 0) break; 124b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write(val); 125b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i++; 126b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } else { 127b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write(val); 128b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i += 2; 129b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 130b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 131b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '0': 132b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '1': 133b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '2': 134b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '3': 135b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '4': 136b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '5': 137b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '6': 138b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff case '7': 139b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff val = asciiEncoded.charAt(i) - '0'; 140b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i++; 141b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') { 142b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff val = val * 8 + asciiEncoded.charAt(i) - '0'; 143b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i++; 144b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 145b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff if (asciiEncoded.charAt(i) >= '0' && asciiEncoded.charAt(i) <= '7') { 146b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff val = val * 8 + asciiEncoded.charAt(i) - '0'; 147b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i++; 148b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 149b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write(val); 150b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 151b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff default: 152b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 153b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 154b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 155b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff default: 156b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff octets.write(c); 157b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff i++; 158b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff break; 159b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 160b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 161b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 162b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 163b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff @Override 164b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public String toString() { 165462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff byte[] ssidBytes = octets.toByteArray(); 166462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff // Supplicant returns \x00\x00\x00\x00\x00\x00\x00\x00 hex string 167462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff // for a hidden access point. Make sure we maintain the previous 168462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff // behavior of returning empty string for this case. 169462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff if (octets.size() <= 0 || isArrayAllZeroes(ssidBytes)) return ""; 170b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff // TODO: Handle conversion to other charsets upon failure 171b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff Charset charset = Charset.forName("UTF-8"); 172b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff CharsetDecoder decoder = charset.newDecoder() 173b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff .onMalformedInput(CodingErrorAction.REPLACE) 174b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff .onUnmappableCharacter(CodingErrorAction.REPLACE); 175b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff CharBuffer out = CharBuffer.allocate(32); 176b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 177462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff CoderResult result = decoder.decode(ByteBuffer.wrap(ssidBytes), out, true); 178b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff out.flip(); 179b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff if (result.isError()) { 180b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return NONE; 181b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 182b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return out.toString(); 183b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 184b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 185462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff private boolean isArrayAllZeroes(byte[] ssidBytes) { 186462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff for (int i = 0; i< ssidBytes.length; i++) { 187462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff if (ssidBytes[i] != 0) return false; 188462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff } 189462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff return true; 190462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff } 191462ff630e441f5bc36c4b926ce81bdb35fe7d04bIrfan Sheriff 192b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff /** @hide */ 193b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public byte[] getOctets() { 194b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return octets.toByteArray(); 195b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 196b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 197b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff /** @hide */ 198b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public String getHexString() { 199b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff String out = "0x"; 200b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff byte[] ssidbytes = getOctets(); 201b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff for (int i = 0; i < octets.size(); i++) { 202b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff out += String.format("%02x", ssidbytes[i]); 203b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 204b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return out; 205b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 206b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 207b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff /** Implement the Parcelable interface {@hide} */ 208b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public int describeContents() { 209b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return 0; 210b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 211b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 212b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff /** Implement the Parcelable interface {@hide} */ 213b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public void writeToParcel(Parcel dest, int flags) { 214b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff dest.writeInt(octets.size()); 215b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff dest.writeByteArray(octets.toByteArray()); 216b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 217b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 218b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff /** Implement the Parcelable interface {@hide} */ 219b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public static final Creator<WifiSsid> CREATOR = 220b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff new Creator<WifiSsid>() { 221b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public WifiSsid createFromParcel(Parcel in) { 222b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff WifiSsid ssid = new WifiSsid(); 223b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff int length = in.readInt(); 224b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff byte b[] = new byte[length]; 225b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff in.readByteArray(b); 226b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff ssid.octets.write(b, 0, length); 227b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return ssid; 228b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 229b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff 230b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff public WifiSsid[] newArray(int size) { 231b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff return new WifiSsid[size]; 232b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff } 233b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff }; 234b6deeed3ceff9e0f754697987b7c724901996082Irfan Sheriff} 235