XmlUtil.java revision 06a2281303248446bacc87a00ab66ea1fdf0392d
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; 29 30import com.android.internal.util.XmlUtils; 31 32import org.xmlpull.v1.XmlPullParser; 33import org.xmlpull.v1.XmlPullParserException; 34import org.xmlpull.v1.XmlSerializer; 35 36import java.io.IOException; 37import java.net.Inet4Address; 38import java.net.InetAddress; 39import java.util.BitSet; 40 41/** 42 * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core. 43 * The utility provides methods to write/parse section headers and write/parse values. 44 * This utility is designed for formatting the XML into the following format: 45 * <Document Header> 46 * <Section 1 Header> 47 * <Value 1> 48 * <Value 2> 49 * ... 50 * <Sub Section 1 Header> 51 * <Value 1> 52 * <Value 2> 53 * ... 54 * </Sub Section 1 Header> 55 * </Section 1 Header> 56 * </Document Header> 57 */ 58public class XmlUtil { 59 private static final String TAG = "WifiXmlUtil"; 60 61 /** 62 * Ensure that the XML stream is at a start tag or the end of document. 63 * 64 * @throws XmlPullParserException if parsing errors occur. 65 */ 66 private static void gotoStartTag(XmlPullParser in) 67 throws XmlPullParserException, IOException { 68 int type = in.getEventType(); 69 while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { 70 type = in.next(); 71 } 72 } 73 74 /** 75 * Ensure that the XML stream is at an end tag or the end of document. 76 * 77 * @throws XmlPullParserException if parsing errors occur. 78 */ 79 private static void gotoEndTag(XmlPullParser in) 80 throws XmlPullParserException, IOException { 81 int type = in.getEventType(); 82 while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) { 83 type = in.next(); 84 } 85 } 86 87 /** 88 * Start processing the XML stream at the document header. 89 * 90 * @param in XmlPullParser instance pointing to the XML stream. 91 * @param headerName expected name for the start tag. 92 * @throws XmlPullParserException if parsing errors occur. 93 */ 94 public static void gotoDocumentStart(XmlPullParser in, String headerName) 95 throws XmlPullParserException, IOException { 96 XmlUtils.beginDocument(in, headerName); 97 } 98 99 /** 100 * Move the XML stream to the next section header. The provided outerDepth is used to find 101 * sub sections within that depth. 102 * 103 * @param in XmlPullParser instance pointing to the XML stream. 104 * @param headerName expected name for the start tag. 105 * @param outerDepth Find section within this depth. 106 * @return {@code true} if a start tag with the provided name is found, {@code false} otherwise 107 * @throws XmlPullParserException if parsing errors occur. 108 */ 109 public static boolean gotoNextSection(XmlPullParser in, String headerName, int outerDepth) 110 throws XmlPullParserException, IOException { 111 while (XmlUtils.nextElementWithin(in, outerDepth)) { 112 if (in.getName().equals(headerName)) { 113 return true; 114 } 115 } 116 return false; 117 } 118 119 /** 120 * Checks if the stream is at the end of a section of values. This moves the stream to next tag 121 * and checks if it finds an end tag at the specified depth. 122 * 123 * @param in XmlPullParser instance pointing to the XML stream. 124 * @param sectionDepth depth of the start tag of this section. Used to match the end tag. 125 * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise 126 * @throws XmlPullParserException if parsing errors occur. 127 */ 128 public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth) 129 throws XmlPullParserException, IOException { 130 return (in.nextTag() == XmlPullParser.END_TAG && in.getDepth() == sectionDepth); 131 } 132 133 /** 134 * Read the current value in the XML stream using core XmlUtils and stores the retrieved 135 * value name in the string provided. This method reads the value contained in current start 136 * tag. 137 * Note: Because there could be genuine null values being read from the XML, this method raises 138 * an exception to indicate errors. 139 * 140 * @param in XmlPullParser instance pointing to the XML stream. 141 * @param valueName An array of one string, used to return the name attribute 142 * of the value's tag. 143 * @return value retrieved from the XML stream. 144 * @throws XmlPullParserException if parsing errors occur. 145 */ 146 public static Object readCurrentValue(XmlPullParser in, String[] valueName) 147 throws XmlPullParserException, IOException { 148 Object value = XmlUtils.readValueXml(in, valueName); 149 // XmlUtils.readValue does not always move the stream to the end of the tag. So, move 150 // it to the end tag before returning from here. 151 gotoEndTag(in); 152 return value; 153 } 154 155 /** 156 * Read the next value in the XML stream using core XmlUtils and ensure that it matches the 157 * provided name. This method moves the stream to the next start tag and reads the value 158 * contained in it. 159 * Note: Because there could be genuine null values being read from the XML, this method raises 160 * an exception to indicate errors. 161 * 162 * @param in XmlPullParser instance pointing to the XML stream. 163 * @return value retrieved from the XML stream. 164 * @throws XmlPullParserException if the value read does not match |expectedName|, 165 * or if parsing errors occur. 166 */ 167 public static Object readNextValueWithName(XmlPullParser in, String expectedName) 168 throws XmlPullParserException, IOException { 169 String[] valueName = new String[1]; 170 XmlUtils.nextElement(in); 171 Object value = readCurrentValue(in, valueName); 172 if (valueName[0].equals(expectedName)) { 173 return value; 174 } 175 throw new XmlPullParserException( 176 "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]); 177 } 178 179 /** 180 * Write the XML document start with the provided document header name. 181 * 182 * @param out XmlSerializer instance pointing to the XML stream. 183 * @param headerName name for the start tag. 184 */ 185 public static void writeDocumentStart(XmlSerializer out, String headerName) 186 throws IOException { 187 out.startDocument(null, true); 188 out.startTag(null, headerName); 189 } 190 191 /** 192 * Write the XML document end with the provided document header name. 193 * 194 * @param out XmlSerializer instance pointing to the XML stream. 195 * @param headerName name for the end tag. 196 */ 197 public static void writeDocumentEnd(XmlSerializer out, String headerName) 198 throws IOException { 199 out.endTag(null, headerName); 200 out.endDocument(); 201 } 202 203 /** 204 * Write a section start header tag with the provided section name. 205 * 206 * @param out XmlSerializer instance pointing to the XML stream. 207 * @param headerName name for the start tag. 208 */ 209 public static void writeNextSectionStart(XmlSerializer out, String headerName) 210 throws IOException { 211 out.startTag(null, headerName); 212 } 213 214 /** 215 * Write a section end header tag with the provided section name. 216 * 217 * @param out XmlSerializer instance pointing to the XML stream. 218 * @param headerName name for the end tag. 219 */ 220 public static void writeNextSectionEnd(XmlSerializer out, String headerName) 221 throws IOException { 222 out.endTag(null, headerName); 223 } 224 225 /** 226 * Write the value with the provided name in the XML stream using core XmlUtils. 227 * 228 * @param out XmlSerializer instance pointing to the XML stream. 229 * @param name name of the value. 230 * @param value value to be written. 231 */ 232 public static void writeNextValue(XmlSerializer out, String name, Object value) 233 throws XmlPullParserException, IOException { 234 XmlUtils.writeValueXml(value, name, out); 235 } 236 237 /** 238 * Utility class to serialize and deseriaize WifConfiguration object to XML & vice versa. 239 * This is used by both #com.android.server.wifi.WifiConfigStore & 240 * #com.android.server.wifi.WifiBackupRestore modules. 241 * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store. 242 * There is only 1 version of |parseXmlToConfiguration| for both backup & config store. 243 * The parse method is written so that any element added/deleted in future revisions can 244 * be easily handled. 245 */ 246 public static class WifiConfigurationXmlUtil { 247 /** 248 * List of XML tags corresponding to WifiConfiguration object elements. 249 */ 250 public static final String XML_TAG_SSID = "SSID"; 251 public static final String XML_TAG_BSSID = "BSSID"; 252 public static final String XML_TAG_CONFIG_KEY = "ConfigKey"; 253 public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey"; 254 public static final String XML_TAG_WEP_KEYS = "WEPKeys"; 255 public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; 256 public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; 257 public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; 258 public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols"; 259 public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; 260 public static final String XML_TAG_SHARED = "Shared"; 261 public static final String XML_TAG_CREATOR_UID = "CreatorUid"; 262 263 /** 264 * Write WepKeys to the XML stream. 265 * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements 266 * are set to null. User may chose to set any one of the key elements in WifiConfiguration. 267 * XmlUtils serialization doesn't handle this array of nulls well . 268 * So, write empty strings if some of the keys are not initialized and null if all of 269 * the elements are empty. 270 */ 271 private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys) 272 throws XmlPullParserException, IOException { 273 String[] wepKeysToWrite = new String[wepKeys.length]; 274 boolean hasWepKey = false; 275 for (int i = 0; i < wepKeys.length; i++) { 276 if (wepKeys[i] == null) { 277 wepKeysToWrite[i] = new String(); 278 } else { 279 wepKeysToWrite[i] = wepKeys[i]; 280 hasWepKey = true; 281 } 282 } 283 if (hasWepKey) { 284 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite); 285 } else { 286 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null); 287 } 288 } 289 290 /** 291 * Write the Configuration data elements that are common for backup & config store to the 292 * XML stream. 293 * 294 * @param out XmlSerializer instance pointing to the XML stream. 295 * @param configuration WifiConfiguration object to be serialized. 296 */ 297 public static void writeCommonWifiConfigurationElementsToXml(XmlSerializer out, 298 WifiConfiguration configuration) 299 throws XmlPullParserException, IOException { 300 XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey()); 301 XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); 302 XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); 303 XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey); 304 writeWepKeysToXml(out, configuration.wepKeys); 305 XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); 306 XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); 307 XmlUtil.writeNextValue( 308 out, XML_TAG_ALLOWED_KEY_MGMT, 309 configuration.allowedKeyManagement.toByteArray()); 310 XmlUtil.writeNextValue( 311 out, XML_TAG_ALLOWED_PROTOCOLS, 312 configuration.allowedProtocols.toByteArray()); 313 XmlUtil.writeNextValue( 314 out, XML_TAG_ALLOWED_AUTH_ALGOS, 315 configuration.allowedAuthAlgorithms.toByteArray()); 316 XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared); 317 XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid); 318 } 319 320 /** 321 * Write the Configuration data elements for backup from the provided Configuration to the 322 * XML stream. 323 * Note: This is a subset of the elements serialized for config store. 324 * 325 * @param out XmlSerializer instance pointing to the XML stream. 326 * @param configuration WifiConfiguration object to be serialized. 327 */ 328 public static void writeWifiConfigurationToXmlForBackup(XmlSerializer out, 329 WifiConfiguration configuration) 330 throws XmlPullParserException, IOException { 331 writeCommonWifiConfigurationElementsToXml(out, configuration); 332 } 333 334 /** 335 * Write the Configuration data elements for config store from the provided Configuration 336 * to the XML stream. 337 */ 338 public static void writeWifiConfigurationToXmlForConfigStore(XmlSerializer out, 339 WifiConfiguration configuration) 340 throws XmlPullParserException, IOException { 341 writeCommonWifiConfigurationElementsToXml(out, configuration); 342 // TODO: Will need to add more elements which needs to be persisted. 343 } 344 345 /** 346 * Populate wepKeys array elements only if they were non-empty in the backup data. 347 * @throws XmlPullParserException if parsing errors occur. 348 */ 349 private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) 350 throws XmlPullParserException, IOException { 351 String[] wepKeysInData = (String[]) value; 352 if (wepKeysInData == null) { 353 return; 354 } 355 if (wepKeysInData.length != wepKeys.length) { 356 throw new XmlPullParserException( 357 "Invalid Wep Keys length: " + wepKeysInData.length); 358 } 359 for (int i = 0; i < wepKeys.length; i++) { 360 if (wepKeysInData[i].isEmpty()) { 361 wepKeys[i] = null; 362 } else { 363 wepKeys[i] = wepKeysInData[i]; 364 } 365 } 366 } 367 368 /** 369 * Parses the configuration data elements from the provided XML stream to a Configuration. 370 * Note: This is used for parsing both backup data and config store data. Looping through 371 * the tags make it easy to add or remove elements in the future versions if needed. 372 * 373 * @param in XmlPullParser instance pointing to the XML stream. 374 * @param outerTagDepth depth of the outer tag in the XML document. 375 * @return WifiConfiguration object if parsing is successful, null otherwise. 376 */ 377 public static WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, 378 int outerTagDepth) 379 throws XmlPullParserException, IOException { 380 WifiConfiguration configuration = new WifiConfiguration(); 381 String configKeyInData = null; 382 383 // Loop through and parse out all the elements from the stream within this section. 384 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 385 String[] valueName = new String[1]; 386 Object value = XmlUtil.readCurrentValue(in, valueName); 387 if (valueName[0] == null) { 388 Log.e(TAG, "Missing value name"); 389 return null; 390 } 391 switch (valueName[0]) { 392 case XML_TAG_CONFIG_KEY: 393 configKeyInData = (String) value; 394 break; 395 case XML_TAG_SSID: 396 configuration.SSID = (String) value; 397 break; 398 case XML_TAG_BSSID: 399 configuration.BSSID = (String) value; 400 break; 401 case XML_TAG_PRE_SHARED_KEY: 402 configuration.preSharedKey = (String) value; 403 break; 404 case XML_TAG_WEP_KEYS: 405 populateWepKeysFromXmlValue(value, configuration.wepKeys); 406 break; 407 case XML_TAG_WEP_TX_KEY_INDEX: 408 configuration.wepTxKeyIndex = (int) value; 409 break; 410 case XML_TAG_HIDDEN_SSID: 411 configuration.hiddenSSID = (boolean) value; 412 break; 413 case XML_TAG_ALLOWED_KEY_MGMT: 414 byte[] allowedKeyMgmt = (byte[]) value; 415 configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); 416 break; 417 case XML_TAG_ALLOWED_PROTOCOLS: 418 byte[] allowedProtocols = (byte[]) value; 419 configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); 420 break; 421 case XML_TAG_ALLOWED_AUTH_ALGOS: 422 byte[] allowedAuthAlgorithms = (byte[]) value; 423 configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); 424 break; 425 case XML_TAG_SHARED: 426 configuration.shared = (boolean) value; 427 break; 428 case XML_TAG_CREATOR_UID: 429 configuration.creatorUid = (int) value; 430 break; 431 default: 432 Log.e(TAG, "Unknown value name found: " + valueName[0]); 433 return null; 434 } 435 } 436 // We should now have all the data to calculate the configKey. Compare it against the 437 // configKey stored in the XML data. 438 String configKeyCalculated = configuration.configKey(); 439 if (configKeyInData == null || !configKeyInData.equals(configKeyCalculated)) { 440 Log.e(TAG, "Configuration key does not match. Retrieved: " + configKeyInData 441 + ", Calculated: " + configKeyCalculated); 442 return null; 443 } 444 return 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