XmlUtil.java revision 2fafcc56fda54b1adf8b6743beaac59dbb84dfec
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.util; 18 19import android.net.IpConfiguration; 20import android.net.IpConfiguration.IpAssignment; 21import android.net.IpConfiguration.ProxySettings; 22import android.net.LinkAddress; 23import android.net.NetworkUtils; 24import android.net.ProxyInfo; 25import android.net.RouteInfo; 26import android.net.StaticIpConfiguration; 27import android.net.wifi.WifiConfiguration; 28import android.util.Log; 29import android.util.Pair; 30 31import com.android.internal.util.XmlUtils; 32 33import org.xmlpull.v1.XmlPullParser; 34import org.xmlpull.v1.XmlPullParserException; 35import org.xmlpull.v1.XmlSerializer; 36 37import java.io.IOException; 38import java.net.Inet4Address; 39import java.net.InetAddress; 40import java.util.BitSet; 41 42/** 43 * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core. 44 * The utility provides methods to write/parse section headers and write/parse values. 45 * This utility is designed for formatting the XML into the following format: 46 * <Document Header> 47 * <Section 1 Header> 48 * <Value 1> 49 * <Value 2> 50 * ... 51 * <Sub Section 1 Header> 52 * <Value 1> 53 * <Value 2> 54 * ... 55 * </Sub Section 1 Header> 56 * </Section 1 Header> 57 * </Document Header> 58 */ 59public class XmlUtil { 60 private static final String TAG = "WifiXmlUtil"; 61 62 /** 63 * Ensure that the XML stream is at a start tag or the end of document. 64 * 65 * @throws XmlPullParserException if parsing errors occur. 66 */ 67 private static void gotoStartTag(XmlPullParser in) 68 throws XmlPullParserException, IOException { 69 int type = in.getEventType(); 70 while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { 71 type = in.next(); 72 } 73 } 74 75 /** 76 * Ensure that the XML stream is at an end tag or the end of document. 77 * 78 * @throws XmlPullParserException if parsing errors occur. 79 */ 80 private static void gotoEndTag(XmlPullParser in) 81 throws XmlPullParserException, IOException { 82 int type = in.getEventType(); 83 while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) { 84 type = in.next(); 85 } 86 } 87 88 /** 89 * Start processing the XML stream at the document header. 90 * 91 * @param in XmlPullParser instance pointing to the XML stream. 92 * @param headerName expected name for the start tag. 93 * @throws XmlPullParserException if parsing errors occur. 94 */ 95 public static void gotoDocumentStart(XmlPullParser in, String headerName) 96 throws XmlPullParserException, IOException { 97 XmlUtils.beginDocument(in, headerName); 98 } 99 100 /** 101 * Move the XML stream to the next section header. The provided outerDepth is used to find 102 * sub sections within that depth. 103 * 104 * @param in XmlPullParser instance pointing to the XML stream. 105 * @param headerName expected name for the start tag. 106 * @param outerDepth Find section within this depth. 107 * @return {@code true} if a start tag with the provided name is found, {@code false} otherwise 108 * @throws XmlPullParserException if parsing errors occur. 109 */ 110 public static boolean gotoNextSection(XmlPullParser in, String headerName, int outerDepth) 111 throws XmlPullParserException, IOException { 112 while (XmlUtils.nextElementWithin(in, outerDepth)) { 113 if (in.getName().equals(headerName)) { 114 return true; 115 } 116 } 117 return false; 118 } 119 120 /** 121 * Checks if the stream is at the end of a section of values. This moves the stream to next tag 122 * and checks if it finds an end tag at the specified depth. 123 * 124 * @param in XmlPullParser instance pointing to the XML stream. 125 * @param sectionDepth depth of the start tag of this section. Used to match the end tag. 126 * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise 127 * @throws XmlPullParserException if parsing errors occur. 128 */ 129 public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth) 130 throws XmlPullParserException, IOException { 131 return (in.nextTag() == XmlPullParser.END_TAG && in.getDepth() == sectionDepth); 132 } 133 134 /** 135 * Read the current value in the XML stream using core XmlUtils and stores the retrieved 136 * value name in the string provided. This method reads the value contained in current start 137 * tag. 138 * Note: Because there could be genuine null values being read from the XML, this method raises 139 * an exception to indicate errors. 140 * 141 * @param in XmlPullParser instance pointing to the XML stream. 142 * @param valueName An array of one string, used to return the name attribute 143 * of the value's tag. 144 * @return value retrieved from the XML stream. 145 * @throws XmlPullParserException if parsing errors occur. 146 */ 147 public static Object readCurrentValue(XmlPullParser in, String[] valueName) 148 throws XmlPullParserException, IOException { 149 Object value = XmlUtils.readValueXml(in, valueName); 150 // XmlUtils.readValue does not always move the stream to the end of the tag. So, move 151 // it to the end tag before returning from here. 152 gotoEndTag(in); 153 return value; 154 } 155 156 /** 157 * Read the next value in the XML stream using core XmlUtils and ensure that it matches the 158 * provided name. This method moves the stream to the next start tag and reads the value 159 * contained in it. 160 * Note: Because there could be genuine null values being read from the XML, this method raises 161 * an exception to indicate errors. 162 * 163 * @param in XmlPullParser instance pointing to the XML stream. 164 * @return value retrieved from the XML stream. 165 * @throws XmlPullParserException if the value read does not match |expectedName|, 166 * or if parsing errors occur. 167 */ 168 public static Object readNextValueWithName(XmlPullParser in, String expectedName) 169 throws XmlPullParserException, IOException { 170 String[] valueName = new String[1]; 171 XmlUtils.nextElement(in); 172 Object value = readCurrentValue(in, valueName); 173 if (valueName[0].equals(expectedName)) { 174 return value; 175 } 176 throw new XmlPullParserException( 177 "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]); 178 } 179 180 /** 181 * Write the XML document start with the provided document header name. 182 * 183 * @param out XmlSerializer instance pointing to the XML stream. 184 * @param headerName name for the start tag. 185 */ 186 public static void writeDocumentStart(XmlSerializer out, String headerName) 187 throws IOException { 188 out.startDocument(null, true); 189 out.startTag(null, headerName); 190 } 191 192 /** 193 * Write the XML document end with the provided document header name. 194 * 195 * @param out XmlSerializer instance pointing to the XML stream. 196 * @param headerName name for the end tag. 197 */ 198 public static void writeDocumentEnd(XmlSerializer out, String headerName) 199 throws IOException { 200 out.endTag(null, headerName); 201 out.endDocument(); 202 } 203 204 /** 205 * Write a section start header tag with the provided section name. 206 * 207 * @param out XmlSerializer instance pointing to the XML stream. 208 * @param headerName name for the start tag. 209 */ 210 public static void writeNextSectionStart(XmlSerializer out, String headerName) 211 throws IOException { 212 out.startTag(null, headerName); 213 } 214 215 /** 216 * Write a section end header tag with the provided section name. 217 * 218 * @param out XmlSerializer instance pointing to the XML stream. 219 * @param headerName name for the end tag. 220 */ 221 public static void writeNextSectionEnd(XmlSerializer out, String headerName) 222 throws IOException { 223 out.endTag(null, headerName); 224 } 225 226 /** 227 * Write the value with the provided name in the XML stream using core XmlUtils. 228 * 229 * @param out XmlSerializer instance pointing to the XML stream. 230 * @param name name of the value. 231 * @param value value to be written. 232 */ 233 public static void writeNextValue(XmlSerializer out, String name, Object value) 234 throws XmlPullParserException, IOException { 235 XmlUtils.writeValueXml(value, name, out); 236 } 237 238 /** 239 * Utility class to serialize and deseriaize WifConfiguration object to XML & vice versa. 240 * This is used by both #com.android.server.wifi.WifiConfigStore & 241 * #com.android.server.wifi.WifiBackupRestore modules. 242 * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store. 243 * There is only 1 version of |parseXmlToConfiguration| for both backup & config store. 244 * The parse method is written so that any element added/deleted in future revisions can 245 * be easily handled. 246 */ 247 public static class WifiConfigurationXmlUtil { 248 /** 249 * List of XML tags corresponding to WifiConfiguration object elements. 250 */ 251 public static final String XML_TAG_SSID = "SSID"; 252 public static final String XML_TAG_BSSID = "BSSID"; 253 public static final String XML_TAG_CONFIG_KEY = "ConfigKey"; 254 public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey"; 255 public static final String XML_TAG_WEP_KEYS = "WEPKeys"; 256 public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; 257 public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; 258 public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; 259 public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols"; 260 public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; 261 public static final String XML_TAG_SHARED = "Shared"; 262 public static final String XML_TAG_CREATOR_UID = "CreatorUid"; 263 public static final String XML_TAG_CREATOR_NAME = "CreatorName"; 264 265 /** 266 * Write WepKeys to the XML stream. 267 * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements 268 * are set to null. User may chose to set any one of the key elements in WifiConfiguration. 269 * XmlUtils serialization doesn't handle this array of nulls well . 270 * So, write empty strings if some of the keys are not initialized and null if all of 271 * the elements are empty. 272 */ 273 private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys) 274 throws XmlPullParserException, IOException { 275 String[] wepKeysToWrite = new String[wepKeys.length]; 276 boolean hasWepKey = false; 277 for (int i = 0; i < wepKeys.length; i++) { 278 if (wepKeys[i] == null) { 279 wepKeysToWrite[i] = new String(); 280 } else { 281 wepKeysToWrite[i] = wepKeys[i]; 282 hasWepKey = true; 283 } 284 } 285 if (hasWepKey) { 286 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite); 287 } else { 288 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null); 289 } 290 } 291 292 /** 293 * Write the Configuration data elements that are common for backup & config store to the 294 * XML stream. 295 * 296 * @param out XmlSerializer instance pointing to the XML stream. 297 * @param configuration WifiConfiguration object to be serialized. 298 */ 299 public static void writeCommonWifiConfigurationElementsToXml(XmlSerializer out, 300 WifiConfiguration configuration) 301 throws XmlPullParserException, IOException { 302 XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey()); 303 XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); 304 XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); 305 XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey); 306 writeWepKeysToXml(out, configuration.wepKeys); 307 XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); 308 XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); 309 XmlUtil.writeNextValue( 310 out, XML_TAG_ALLOWED_KEY_MGMT, 311 configuration.allowedKeyManagement.toByteArray()); 312 XmlUtil.writeNextValue( 313 out, XML_TAG_ALLOWED_PROTOCOLS, 314 configuration.allowedProtocols.toByteArray()); 315 XmlUtil.writeNextValue( 316 out, XML_TAG_ALLOWED_AUTH_ALGOS, 317 configuration.allowedAuthAlgorithms.toByteArray()); 318 XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared); 319 } 320 321 /** 322 * Write the Configuration data elements for backup from the provided Configuration to the 323 * XML stream. 324 * Note: This is a subset of the elements serialized for config store. 325 * 326 * @param out XmlSerializer instance pointing to the XML stream. 327 * @param configuration WifiConfiguration object to be serialized. 328 */ 329 public static void writeWifiConfigurationToXmlForBackup(XmlSerializer out, 330 WifiConfiguration configuration) 331 throws XmlPullParserException, IOException { 332 writeCommonWifiConfigurationElementsToXml(out, configuration); 333 } 334 335 /** 336 * Write the Configuration data elements for config store from the provided Configuration 337 * to the XML stream. 338 */ 339 public static void writeWifiConfigurationToXmlForConfigStore(XmlSerializer out, 340 WifiConfiguration configuration) 341 throws XmlPullParserException, IOException { 342 writeCommonWifiConfigurationElementsToXml(out, configuration); 343 // TODO: Will need to add more elements which needs to be persisted. 344 XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid); 345 XmlUtil.writeNextValue(out, XML_TAG_CREATOR_NAME, configuration.creatorName); 346 } 347 348 /** 349 * Populate wepKeys array elements only if they were non-empty in the backup data. 350 * 351 * @throws XmlPullParserException if parsing errors occur. 352 */ 353 private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) 354 throws XmlPullParserException, IOException { 355 String[] wepKeysInData = (String[]) value; 356 if (wepKeysInData == null) { 357 return; 358 } 359 if (wepKeysInData.length != wepKeys.length) { 360 throw new XmlPullParserException( 361 "Invalid Wep Keys length: " + wepKeysInData.length); 362 } 363 for (int i = 0; i < wepKeys.length; i++) { 364 if (wepKeysInData[i].isEmpty()) { 365 wepKeys[i] = null; 366 } else { 367 wepKeys[i] = wepKeysInData[i]; 368 } 369 } 370 } 371 372 /** 373 * Parses the configuration data elements from the provided XML stream to a Configuration. 374 * Note: This is used for parsing both backup data and config store data. Looping through 375 * the tags make it easy to add or remove elements in the future versions if needed. 376 * 377 * @param in XmlPullParser instance pointing to the XML stream. 378 * @param outerTagDepth depth of the outer tag in the XML document. 379 * @return Pair<Config key, WifiConfiguration object> if parsing is successful, 380 * null otherwise. 381 */ 382 public static Pair<String, WifiConfiguration> parseWifiConfigurationFromXml( 383 XmlPullParser in, int outerTagDepth) 384 throws XmlPullParserException, IOException { 385 WifiConfiguration configuration = new WifiConfiguration(); 386 String configKeyInData = null; 387 388 // Loop through and parse out all the elements from the stream within this section. 389 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 390 String[] valueName = new String[1]; 391 Object value = XmlUtil.readCurrentValue(in, valueName); 392 if (valueName[0] == null) { 393 Log.e(TAG, "Missing value name"); 394 return null; 395 } 396 switch (valueName[0]) { 397 case XML_TAG_CONFIG_KEY: 398 configKeyInData = (String) value; 399 break; 400 case XML_TAG_SSID: 401 configuration.SSID = (String) value; 402 break; 403 case XML_TAG_BSSID: 404 configuration.BSSID = (String) value; 405 break; 406 case XML_TAG_PRE_SHARED_KEY: 407 configuration.preSharedKey = (String) value; 408 break; 409 case XML_TAG_WEP_KEYS: 410 populateWepKeysFromXmlValue(value, configuration.wepKeys); 411 break; 412 case XML_TAG_WEP_TX_KEY_INDEX: 413 configuration.wepTxKeyIndex = (int) value; 414 break; 415 case XML_TAG_HIDDEN_SSID: 416 configuration.hiddenSSID = (boolean) value; 417 break; 418 case XML_TAG_ALLOWED_KEY_MGMT: 419 byte[] allowedKeyMgmt = (byte[]) value; 420 configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); 421 break; 422 case XML_TAG_ALLOWED_PROTOCOLS: 423 byte[] allowedProtocols = (byte[]) value; 424 configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); 425 break; 426 case XML_TAG_ALLOWED_AUTH_ALGOS: 427 byte[] allowedAuthAlgorithms = (byte[]) value; 428 configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); 429 break; 430 case XML_TAG_SHARED: 431 configuration.shared = (boolean) value; 432 break; 433 case XML_TAG_CREATOR_UID: 434 configuration.creatorUid = (int) value; 435 break; 436 case XML_TAG_CREATOR_NAME: 437 configuration.creatorName = (String) value; 438 break; 439 default: 440 Log.e(TAG, "Unknown value name found: " + valueName[0]); 441 return null; 442 } 443 } 444 return Pair.create(configKeyInData, configuration); 445 } 446 } 447 448 /** 449 * Utility class to serialize and deseriaize IpConfiguration object to XML & vice versa. 450 * This is used by both #com.android.server.wifi.WifiConfigStore & 451 * #com.android.server.wifi.WifiBackupRestore modules. 452 */ 453 public static class IpConfigurationXmlUtil { 454 455 /** 456 * List of XML tags corresponding to IpConfiguration object elements. 457 */ 458 public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment"; 459 public static final String XML_TAG_LINK_ADDRESS = "LinkAddress"; 460 public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength"; 461 public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress"; 462 public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers"; 463 public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings"; 464 public static final String XML_TAG_PROXY_HOST = "ProxyHost"; 465 public static final String XML_TAG_PROXY_PORT = "ProxyPort"; 466 public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac"; 467 public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList"; 468 469 /** 470 * Write the static IP configuration data elements to XML stream. 471 */ 472 private static void writeStaticIpConfigurationToXml(XmlSerializer out, 473 StaticIpConfiguration staticIpConfiguration) 474 throws XmlPullParserException, IOException { 475 if (staticIpConfiguration.ipAddress != null) { 476 XmlUtil.writeNextValue( 477 out, XML_TAG_LINK_ADDRESS, 478 staticIpConfiguration.ipAddress.getAddress().getHostAddress()); 479 XmlUtil.writeNextValue( 480 out, XML_TAG_LINK_PREFIX_LENGTH, 481 staticIpConfiguration.ipAddress.getPrefixLength()); 482 } else { 483 XmlUtil.writeNextValue( 484 out, XML_TAG_LINK_ADDRESS, null); 485 XmlUtil.writeNextValue( 486 out, XML_TAG_LINK_PREFIX_LENGTH, null); 487 } 488 if (staticIpConfiguration.gateway != null) { 489 XmlUtil.writeNextValue( 490 out, XML_TAG_GATEWAY_ADDRESS, 491 staticIpConfiguration.gateway.getHostAddress()); 492 } else { 493 XmlUtil.writeNextValue( 494 out, XML_TAG_GATEWAY_ADDRESS, null); 495 496 } 497 if (staticIpConfiguration.dnsServers != null) { 498 // Create a string array of DNS server addresses 499 String[] dnsServers = new String[staticIpConfiguration.dnsServers.size()]; 500 int dnsServerIdx = 0; 501 for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { 502 dnsServers[dnsServerIdx++] = inetAddr.getHostAddress(); 503 } 504 XmlUtil.writeNextValue( 505 out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers); 506 } else { 507 XmlUtil.writeNextValue( 508 out, XML_TAG_DNS_SERVER_ADDRESSES, null); 509 } 510 } 511 512 /** 513 * Write the IP configuration data elements from the provided Configuration to the XML 514 * stream. 515 */ 516 public static void writeIpConfigurationToXml(XmlSerializer out, 517 IpConfiguration ipConfiguration) 518 throws XmlPullParserException, IOException { 519 // Write IP assignment settings 520 XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT, 521 ipConfiguration.ipAssignment.toString()); 522 switch (ipConfiguration.ipAssignment) { 523 case STATIC: 524 writeStaticIpConfigurationToXml( 525 out, ipConfiguration.getStaticIpConfiguration()); 526 break; 527 default: 528 break; 529 } 530 531 // Write proxy settings 532 XmlUtil.writeNextValue( 533 out, XML_TAG_PROXY_SETTINGS, 534 ipConfiguration.proxySettings.toString()); 535 switch (ipConfiguration.proxySettings) { 536 case STATIC: 537 XmlUtil.writeNextValue( 538 out, XML_TAG_PROXY_HOST, 539 ipConfiguration.httpProxy.getHost()); 540 XmlUtil.writeNextValue( 541 out, XML_TAG_PROXY_PORT, 542 ipConfiguration.httpProxy.getPort()); 543 XmlUtil.writeNextValue( 544 out, XML_TAG_PROXY_EXCLUSION_LIST, 545 ipConfiguration.httpProxy.getExclusionListAsString()); 546 break; 547 case PAC: 548 XmlUtil.writeNextValue( 549 out, XML_TAG_PROXY_PAC_FILE, 550 ipConfiguration.httpProxy.getPacFileUrl().toString()); 551 break; 552 default: 553 break; 554 } 555 } 556 557 /** 558 * Parse out the static IP configuration from the XML stream. 559 */ 560 private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in) 561 throws XmlPullParserException, IOException { 562 StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); 563 564 String linkAddressString = 565 (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS); 566 Integer linkPrefixLength = 567 (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH); 568 if (linkAddressString != null && linkPrefixLength != null) { 569 LinkAddress linkAddress = new LinkAddress( 570 NetworkUtils.numericToInetAddress(linkAddressString), 571 linkPrefixLength); 572 if (linkAddress.getAddress() instanceof Inet4Address) { 573 staticIpConfiguration.ipAddress = linkAddress; 574 } else { 575 Log.w(TAG, "Non-IPv4 address: " + linkAddress); 576 } 577 } 578 String gatewayAddressString = 579 (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS); 580 if (gatewayAddressString != null) { 581 LinkAddress dest = null; 582 InetAddress gateway = 583 NetworkUtils.numericToInetAddress(gatewayAddressString); 584 RouteInfo route = new RouteInfo(dest, gateway); 585 if (route.isIPv4Default()) { 586 staticIpConfiguration.gateway = gateway; 587 } else { 588 Log.w(TAG, "Non-IPv4 default route: " + route); 589 } 590 } 591 String[] dnsServerAddressesString = 592 (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES); 593 if (dnsServerAddressesString != null) { 594 for (String dnsServerAddressString : dnsServerAddressesString) { 595 InetAddress dnsServerAddress = 596 NetworkUtils.numericToInetAddress(dnsServerAddressString); 597 staticIpConfiguration.dnsServers.add(dnsServerAddress); 598 } 599 } 600 return staticIpConfiguration; 601 } 602 603 /** 604 * Parses the IP configuration data elements from the provided XML stream to a 605 * IpConfiguration. 606 * 607 * @param in XmlPullParser instance pointing to the XML stream. 608 * @param outerTagDepth depth of the outer tag in the XML document. 609 * @return IpConfiguration object if parsing is successful, null otherwise. 610 */ 611 public static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, 612 int outerTagDepth) 613 throws XmlPullParserException, IOException { 614 IpConfiguration ipConfiguration = new IpConfiguration(); 615 616 // Parse out the IP assignment info first. 617 String ipAssignmentString = 618 (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT); 619 IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); 620 ipConfiguration.setIpAssignment(ipAssignment); 621 switch (ipAssignment) { 622 case STATIC: 623 ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in)); 624 break; 625 case DHCP: 626 case UNASSIGNED: 627 break; 628 default: 629 Log.wtf(TAG, "Unknown ip assignment type: " + ipAssignment); 630 return null; 631 } 632 633 // Parse out the proxy settings next. 634 String proxySettingsString = 635 (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS); 636 ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); 637 ipConfiguration.setProxySettings(proxySettings); 638 switch (proxySettings) { 639 case STATIC: 640 String proxyHost = 641 (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST); 642 int proxyPort = 643 (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT); 644 String proxyExclusionList = 645 (String) XmlUtil.readNextValueWithName( 646 in, XML_TAG_PROXY_EXCLUSION_LIST); 647 ipConfiguration.setHttpProxy( 648 new ProxyInfo(proxyHost, proxyPort, proxyExclusionList)); 649 break; 650 case PAC: 651 String proxyPacFile = 652 (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE); 653 ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile)); 654 break; 655 case NONE: 656 case UNASSIGNED: 657 break; 658 default: 659 Log.wtf(TAG, "Unknown proxy settings type: " + proxySettings); 660 return null; 661 } 662 return ipConfiguration; 663 } 664 } 665} 666 667