1+ package tk.superl2.xwifi
2+
3+ import android.util.Log
4+ import android.util.Xml
5+ import org.xmlpull.v1.XmlPullParser
6+ import org.xmlpull.v1.XmlPullParserException
7+ import java.io.IOException
8+ import java.util.*
9+
10+ object WifiEntryLoader {
11+ private const val mOreoLocation = " /data/misc/wifi/WifiConfigStore.xml"
12+
13+ @Throws(XmlPullParserException ::class , IOException ::class )
14+ private fun readNetworkList (parser : XmlPullParser ): ArrayList <WifiEntry > {
15+ val result = ArrayList <WifiEntry >()
16+ parser.require(XmlPullParser .START_TAG , null , " NetworkList" )
17+ var doLoop = true
18+ while (doLoop) {
19+ try {
20+ parser.next()
21+ var tagName: String? = parser.name
22+ if (tagName == null ) {
23+ tagName = " "
24+ }
25+ doLoop = ! tagName.equals(" NetworkList" , ignoreCase = true )
26+ if (parser.eventType != XmlPullParser .START_TAG ) {
27+ continue
28+ }
29+
30+ if (tagName == " Network" ) {
31+ val newWifi = readNetworkEntry(parser)
32+ if (newWifi.title.isNotEmpty()) {
33+ result.add(newWifi)
34+ }
35+ } else {
36+ skip(parser)
37+ }
38+ } catch (e: Exception ) {
39+ Log .e(" LoadData.NetworkList" , e.message)
40+ doLoop = false
41+ }
42+
43+ }
44+ return result
45+ }
46+
47+ // Parses a "Network" entry
48+ @Throws(XmlPullParserException ::class , IOException ::class )
49+ private fun readNetworkEntry (parser : XmlPullParser ): WifiEntry {
50+ parser.require(XmlPullParser .START_TAG , null , " Network" )
51+ var result = WifiEntry ()
52+ while (parser.next() != XmlPullParser .END_TAG ) {
53+ if (parser.eventType != XmlPullParser .START_TAG ) {
54+ continue
55+ }
56+ val tagName = parser.name
57+ // Starts by looking for the entry tag
58+ when (tagName) {
59+ " WifiConfiguration" -> result = readWiFiConfig(parser, result)
60+ " WifiEnterpriseConfiguration" -> result.type = WifiEntry .Type .ENTERPRISE
61+ else -> skip(parser)
62+ }
63+ }
64+ return result
65+ }
66+
67+ // Parses a "WifiConfiguration" entry
68+ @Throws(XmlPullParserException ::class , IOException ::class )
69+ private fun readWiFiConfig (parser : XmlPullParser , result : WifiEntry ): WifiEntry {
70+ try {
71+ while (parser.next() != XmlPullParser .END_TAG ) {
72+ if (parser.eventType != XmlPullParser .START_TAG ) {
73+ continue
74+ }
75+ val tagName = parser.name
76+ val name = parser.getAttributeValue(null , " name" )
77+ if (name == " SSID" && ! tagName.equals(" null" , ignoreCase = true )) {
78+ result.title = readTag(parser, tagName)
79+ } else if (name == " PreSharedKey" && ! tagName.equals(" null" , ignoreCase = true )) {
80+ val newPwd = readTag(parser, tagName)
81+ if (newPwd.isNotEmpty()) {
82+ result.password = newPwd
83+ result.type = WifiEntry .Type .WPA
84+ }
85+ } else if (name == " WEPKeys" && ! tagName.equals(" null" , ignoreCase = true )) {
86+ result.type = WifiEntry .Type .WEP
87+ if (tagName.equals(" string-array" , ignoreCase = true )) {
88+ try {
89+ val numQty = Integer .parseInt(parser.getAttributeValue(null , " num" ))
90+ var loopQty = 0
91+ while (parser.next() != XmlPullParser .END_DOCUMENT && loopQty < numQty) {
92+ val innerTagName = parser.name
93+ if (innerTagName != null && innerTagName.equals(" item" , ignoreCase = true )) {
94+ loopQty++
95+ val newPwd = parser.getAttributeValue(null , " value" )
96+ if (newPwd.isNotEmpty()) {
97+ result.password = newPwd
98+ }
99+ }
100+ }
101+ } catch (error: Exception ) {
102+ parser.name
103+ }
104+
105+ } else {
106+ val newPwd = readTag(parser, tagName)
107+ if (newPwd.isNotEmpty()) {
108+ result.password = readTag(parser, tagName)
109+ }
110+ }
111+ } else {
112+ skip(parser)
113+ }
114+ }
115+ } catch (error: Exception ) {
116+ Log .e(" LoadData.readWiFiConfig" , error.message + " \n\n Parser: " + parser.text)
117+ }
118+
119+ return result
120+ }
121+
122+ // Return the text for a specified tag.
123+ @Throws(IOException ::class , XmlPullParserException ::class )
124+ private fun readTag (parser : XmlPullParser , tagName : String ): String {
125+ parser.require(XmlPullParser .START_TAG , null , tagName)
126+ var result = " "
127+ if (parser.next() == XmlPullParser .TEXT ) {
128+ result = parser.text
129+ parser.nextTag()
130+ }
131+ parser.require(XmlPullParser .END_TAG , null , tagName)
132+ if (tagName.equals(" string" , ignoreCase = true ) && Character .toString(result[0 ]) == " \" " ) {
133+ result = result.substring(1 , result.length - 1 )
134+ }
135+ return result
136+ }
137+
138+ // Skips tags the parser isn't interested in. Uses depth to handle nested tags. i.e.,
139+ // if the next tag after a START_TAG isn't a matching END_TAG, it keeps going until it
140+ // finds the matching END_TAG (as indicated by the value of "depth" being 0).
141+ @Throws(XmlPullParserException ::class , IOException ::class )
142+ private fun skip (parser : XmlPullParser ) {
143+ if (parser.eventType != XmlPullParser .START_TAG ) {
144+ throw IllegalStateException ()
145+ }
146+ var depth = 1
147+ while (depth != 0 ) {
148+ when (parser.next()) {
149+ XmlPullParser .END_TAG -> depth--
150+ XmlPullParser .START_TAG -> depth++
151+ }
152+ }
153+ }
154+
155+ fun readOreoFile (): ArrayList <WifiEntry > {
156+ val result = ArrayList <WifiEntry >()
157+ try {
158+ val suOreoProcess = Runtime .getRuntime().exec(" su" )
159+ val suOreoProcessOutputStream = suOreoProcess.outputStream
160+ suOreoProcessOutputStream.write(" /system/bin/cat $mOreoLocation \n " .toByteArray())
161+ suOreoProcessOutputStream.write(" exit\n " .toByteArray())
162+ suOreoProcessOutputStream.flush()
163+ suOreoProcessOutputStream.close()
164+ try {
165+ suOreoProcess.waitFor()
166+ } catch (e: InterruptedException ) {
167+ e.printStackTrace()
168+ }
169+
170+ val parser = Xml .newPullParser()
171+ parser.setFeature(XmlPullParser .FEATURE_PROCESS_NAMESPACES , false )
172+ parser.setInput(suOreoProcess.inputStream, " UTF-8" )
173+ while (parser.next() != XmlPullParser .END_DOCUMENT ) {
174+ if (parser.eventType != XmlPullParser .START_TAG ) {
175+ continue
176+ }
177+ if (parser.name.equals(" NetworkList" , ignoreCase = true )) {
178+ // Process the <Network> entries in the list
179+ result.addAll(readNetworkList(parser))
180+ }
181+ }
182+ } catch (e: IOException ) {
183+ e.printStackTrace()
184+ } catch (e: XmlPullParserException ) {
185+ e.printStackTrace()
186+ } finally {
187+ return if (result.isNotEmpty()) {
188+ result
189+ } else {
190+ throw WifiUnparseableException ()
191+ }
192+ }
193+ }
194+ }
195+
196+ class WifiUnparseableException (message : String = " Wifi list could not be parsed." ): Exception(message)
0 commit comments