/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi;

import android.net.IpConfiguration;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.os.Process;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;

import com.android.internal.util.FastXmlSerializer;
import com.android.server.wifi.util.IpConfigStore;
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.XmlUtil;
import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil;
import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Class used to backup/restore data using the SettingsBackupAgent.
 * There are 2 symmetric API's exposed here:
 * 1. retrieveBackupDataFromConfigurations: Retrieve the configuration data to be backed up.
 * 2. retrieveConfigurationsFromBackupData: Restore the configuration using the provided data.
 * The byte stream to be backed up is XML encoded and versioned to migrate the data easily across
 * revisions.
 */
public class WifiBackupRestore {
    private static final String TAG = "WifiBackupRestore";

    /**
     * Current backup data version.
     * Note: before Android P this used to be an {@code int}, however support for minor versions
     * has been added in Android P. Currently this field is a {@code float} representing
     * "majorVersion.minorVersion" of the backed up data. MinorVersion starts with 0 and should
     * be incremented when necessary. MajorVersion starts with 1 and bumping it up requires
     * also resetting minorVersion to 0.
     *
     * MajorVersion will be incremented for modifications of the XML schema, excluding additive
     * modifications in <WifiConfiguration> and/or <IpConfiguration> tags.
     * Should the major version be bumped up, a new {@link WifiBackupDataParser} parser needs to
     * be added and returned from {@link #getWifiBackupDataParser(int)} ()}.
     * Note that bumping up the major version will result in inability to restore the backup
     * set to those lower versions of SDK_INT that don't support the version.
     *
     * MinorVersion will only be incremented for addition of <WifiConfiguration> and/or
     * <IpConfiguration> tags. Any other modifications to the schema should result in bumping up
     * the major version and resetting the minor version to 0.
     * Note that bumping up only the minor version will still allow restoring the backup set to
     * lower versions of SDK_INT.
     */
    private static final int CURRENT_BACKUP_DATA_MAJOR_VERSION = 1;

    /** This list of older versions will be used to restore data from older backups. */
    /**
     * First version of the backup data format.
     */
    private static final int INITIAL_BACKUP_DATA_VERSION = 1;

    /**
     * List of XML section header tags in the backed up data
     */
    private static final String XML_TAG_DOCUMENT_HEADER = "WifiBackupData";
    private static final String XML_TAG_VERSION = "Version";

    static final String XML_TAG_SECTION_HEADER_NETWORK_LIST = "NetworkList";
    static final String XML_TAG_SECTION_HEADER_NETWORK = "Network";
    static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration";
    static final String XML_TAG_SECTION_HEADER_IP_CONFIGURATION = "IpConfiguration";

    /**
     * Regex to mask out passwords in backup data dump.
     */
    private static final String PSK_MASK_LINE_MATCH_PATTERN =
            "<.*" + WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY + ".*>.*<.*>";
    private static final String PSK_MASK_SEARCH_PATTERN =
            "(<.*" + WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY + ".*>)(.*)(<.*>)";
    private static final String PSK_MASK_REPLACE_PATTERN = "$1*$3";

    private static final String WEP_KEYS_MASK_LINE_START_MATCH_PATTERN =
            "<string-array.*" + WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS + ".*num=\"[0-9]\">";
    private static final String WEP_KEYS_MASK_LINE_END_MATCH_PATTERN = "</string-array>";
    private static final String WEP_KEYS_MASK_SEARCH_PATTERN = "(<.*=)(.*)(/>)";
    private static final String WEP_KEYS_MASK_REPLACE_PATTERN = "$1*$3";

    private final WifiPermissionsUtil mWifiPermissionsUtil;
    /**
     * Verbose logging flag.
     */
    private boolean mVerboseLoggingEnabled = false;

    /**
     * Store the dump of the backup/restore data for debugging. This is only stored when verbose
     * logging is enabled in developer options.
     */
    private byte[] mDebugLastBackupDataRetrieved;
    private byte[] mDebugLastBackupDataRestored;
    private byte[] mDebugLastSupplicantBackupDataRestored;
    private byte[] mDebugLastIpConfigBackupDataRestored;

    public WifiBackupRestore(WifiPermissionsUtil wifiPermissionsUtil) {
        mWifiPermissionsUtil = wifiPermissionsUtil;
    }

    /**
     * Retrieve the version for serialization.
     */
    private Float getVersion() {
        WifiBackupDataParser parser =
                getWifiBackupDataParser(CURRENT_BACKUP_DATA_MAJOR_VERSION);
        if (parser == null) {
            Log.e(TAG, "Major version of backup data is unknown to this Android"
                    + " version; not backing up");
            return null;
        }
        int minorVersion = parser.getHighestSupportedMinorVersion();
        Float version;
        try {
            version = Float.valueOf(
                    CURRENT_BACKUP_DATA_MAJOR_VERSION + "." + minorVersion);
        } catch (NumberFormatException e) {
            Log.e(TAG, "Failed to generate version", e);
            return null;
        }
        return version;
    }

    /**
     * Retrieve an XML byte stream representing the data that needs to be backed up from the
     * provided configurations.
     *
     * @param configurations list of currently saved networks that needs to be backed up.
     * @return Raw byte stream of XML that needs to be backed up.
     */
    public byte[] retrieveBackupDataFromConfigurations(List<WifiConfiguration> configurations) {
        if (configurations == null) {
            Log.e(TAG, "Invalid configuration list received");
            return new byte[0];
        }

        try {
            final XmlSerializer out = new FastXmlSerializer();
            final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            out.setOutput(outputStream, StandardCharsets.UTF_8.name());

            // Start writing the XML stream.
            XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER);

            Float version = getVersion();
            if (version == null) return null;
            XmlUtil.writeNextValue(out, XML_TAG_VERSION, version.floatValue());

            writeNetworkConfigurationsToXml(out, configurations);

            XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER);

            byte[] data = outputStream.toByteArray();

            if (mVerboseLoggingEnabled) {
                mDebugLastBackupDataRetrieved = data;
            }

            return data;
        } catch (XmlPullParserException e) {
            Log.e(TAG, "Error retrieving the backup data: " + e);
        } catch (IOException e) {
            Log.e(TAG, "Error retrieving the backup data: " + e);
        }
        return new byte[0];
    }

    /**
     * Write the list of configurations to the XML stream.
     */
    private void writeNetworkConfigurationsToXml(
            XmlSerializer out, List<WifiConfiguration> configurations)
            throws XmlPullParserException, IOException {
        XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_LIST);
        for (WifiConfiguration configuration : configurations) {
            // We don't want to backup/restore enterprise/passpoint configurations.
            if (configuration.isEnterprise() || configuration.isPasspoint()) {
                continue;
            }
            if (!mWifiPermissionsUtil.checkConfigOverridePermission(configuration.creatorUid)) {
                Log.d(TAG, "Ignoring network from an app with no config override permission: "
                        + configuration.getKey());
                continue;
            }
            // Write this configuration data now.
            XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK);
            writeNetworkConfigurationToXml(out, configuration);
            XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK);
        }
        XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_LIST);
    }

    /**
     * Write the configuration data elements from the provided Configuration to the XML stream.
     * Uses XmlUtils to write the values of each element.
     */
    private void writeNetworkConfigurationToXml(XmlSerializer out, WifiConfiguration configuration)
            throws XmlPullParserException, IOException {
        XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
        WifiConfigurationXmlUtil.writeToXmlForBackup(out, configuration);
        XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
        XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
        IpConfigurationXmlUtil.writeToXml(out, configuration.getIpConfiguration());
        XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
    }

    /**
     * Parse out the configurations from the back up data.
     *
     * @param data raw byte stream representing the XML data.
     * @return list of networks retrieved from the backed up data.
     */
    public List<WifiConfiguration> retrieveConfigurationsFromBackupData(byte[] data) {
        if (data == null || data.length == 0) {
            Log.e(TAG, "Invalid backup data received");
            return null;
        }
        try {
            if (mVerboseLoggingEnabled) {
                mDebugLastBackupDataRestored = data;
            }

            final XmlPullParser in = Xml.newPullParser();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
            in.setInput(inputStream, StandardCharsets.UTF_8.name());

            // Start parsing the XML stream.
            XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER);
            int rootTagDepth = in.getDepth();

            int majorVersion = -1;
            int minorVersion = -1;
            try {
                float version = (float) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION);

                // parse out major and minor versions
                String versionStr = new Float(version).toString();
                int separatorPos = versionStr.indexOf('.');
                if (separatorPos == -1) {
                    majorVersion = Integer.parseInt(versionStr);
                    minorVersion = 0;
                } else {
                    majorVersion = Integer.parseInt(versionStr.substring(0, separatorPos));
                    minorVersion = Integer.parseInt(versionStr.substring(separatorPos + 1));
                }
            } catch (ClassCastException cce) {
                // Integer cannot be cast to Float for data coming from before Android P
                majorVersion = 1;
                minorVersion = 0;
            }
            Log.d(TAG, "Version of backup data - major: " + majorVersion
                    + "; minor: " + minorVersion);

            WifiBackupDataParser parser = getWifiBackupDataParser(majorVersion);
            if (parser == null) {
                Log.w(TAG, "Major version of backup data is unknown to this Android"
                        + " version; not restoring");
                return null;
            } else {
                return parser.parseNetworkConfigurationsFromXml(in, rootTagDepth, minorVersion);
            }
        } catch (XmlPullParserException | IOException | ClassCastException
                | IllegalArgumentException e) {
            Log.e(TAG, "Error parsing the backup data: " + e);
        }
        return null;
    }

    private WifiBackupDataParser getWifiBackupDataParser(int majorVersion) {
        switch (majorVersion) {
            case INITIAL_BACKUP_DATA_VERSION:
                return new WifiBackupDataV1Parser();
            default:
                Log.e(TAG, "Unrecognized majorVersion of backup data: " + majorVersion);
                return null;
        }
    }

    /**
     * Create log dump of the backup data in XML format with the preShared & WEP key masked.
     *
     * PSK keys are written in the following format in XML:
     * <string name="PreSharedKey">WifiBackupRestorePsk</string>
     *
     * WEP Keys are written in following format in XML:
     * <string-array name="WEPKeys" num="4">
     *  <item value="WifiBackupRestoreWep1" />
     *  <item value="WifiBackupRestoreWep2" />
     *  <item value="WifiBackupRestoreWep3" />
     *  <item value="WifiBackupRestoreWep3" />
     * </string-array>
     */
    private String createLogFromBackupData(byte[] data) {
        StringBuilder sb = new StringBuilder();
        try {
            String xmlString = new String(data, StandardCharsets.UTF_8.name());
            boolean wepKeysLine = false;
            for (String line : xmlString.split("\n")) {
                if (line.matches(PSK_MASK_LINE_MATCH_PATTERN)) {
                    line = line.replaceAll(PSK_MASK_SEARCH_PATTERN, PSK_MASK_REPLACE_PATTERN);
                }
                if (line.matches(WEP_KEYS_MASK_LINE_START_MATCH_PATTERN)) {
                    wepKeysLine = true;
                } else if (line.matches(WEP_KEYS_MASK_LINE_END_MATCH_PATTERN)) {
                    wepKeysLine = false;
                } else if (wepKeysLine) {
                    line = line.replaceAll(
                            WEP_KEYS_MASK_SEARCH_PATTERN, WEP_KEYS_MASK_REPLACE_PATTERN);
                }
                sb.append(line).append("\n");
            }
        } catch (UnsupportedEncodingException e) {
            return "";
        }
        return sb.toString();
    }

    /**
     * Restore state from the older supplicant back up data.
     * The old backup data was essentially a backup of wpa_supplicant.conf & ipconfig.txt file.
     *
     * @param supplicantData Raw byte stream of wpa_supplicant.conf
     * @param ipConfigData   Raw byte stream of ipconfig.txt
     * @return list of networks retrieved from the backed up data.
     */
    public List<WifiConfiguration> retrieveConfigurationsFromSupplicantBackupData(
            byte[] supplicantData, byte[] ipConfigData) {
        if (supplicantData == null || supplicantData.length == 0) {
            Log.e(TAG, "Invalid supplicant backup data received");
            return null;
        }

        if (mVerboseLoggingEnabled) {
            mDebugLastSupplicantBackupDataRestored = supplicantData;
            mDebugLastIpConfigBackupDataRestored = ipConfigData;
        }

        SupplicantBackupMigration.SupplicantNetworks supplicantNetworks =
                new SupplicantBackupMigration.SupplicantNetworks();
        // Incorporate the networks present in the backup data.
        char[] restoredAsChars = new char[supplicantData.length];
        for (int i = 0; i < supplicantData.length; i++) {
            restoredAsChars[i] = (char) supplicantData[i];
        }

        BufferedReader in = new BufferedReader(new CharArrayReader(restoredAsChars));
        supplicantNetworks.readNetworksFromStream(in);

        // Retrieve corresponding WifiConfiguration objects.
        List<WifiConfiguration> configurations = supplicantNetworks.retrieveWifiConfigurations();

        // Now retrieve all the IpConfiguration objects and set in the corresponding
        // WifiConfiguration objects if ipconfig data is present.
        if (ipConfigData != null && ipConfigData.length != 0) {
            SparseArray<IpConfiguration> networks =
                    IpConfigStore.readIpAndProxyConfigurations(
                            new ByteArrayInputStream(ipConfigData));
            if (networks != null) {
                for (int i = 0; i < networks.size(); i++) {
                    int id = networks.keyAt(i);
                    for (WifiConfiguration configuration : configurations) {
                        // This is a dangerous lookup, but that's how it is currently written.
                        if (configuration.getKey().hashCode() == id) {
                            configuration.setIpConfiguration(networks.valueAt(i));
                        }
                    }
                }
            } else {
                Log.e(TAG, "Failed to parse ipconfig data");
            }
        } else {
            Log.e(TAG, "Invalid ipconfig backup data received");
        }
        return configurations;
    }

    /**
     * Enable verbose logging.
     *
     * @param verbose verbosity level.
     */
    public void enableVerboseLogging(int verbose) {
        mVerboseLoggingEnabled = (verbose > 0);
        if (!mVerboseLoggingEnabled) {
            mDebugLastBackupDataRetrieved = null;
            mDebugLastBackupDataRestored = null;
            mDebugLastSupplicantBackupDataRestored = null;
            mDebugLastIpConfigBackupDataRestored = null;
        }
    }

    /**
     * Dump out the last backup/restore data if verbose logging is enabled.
     *
     * @param fd   unused
     * @param pw   PrintWriter for writing dump to
     * @param args unused
     */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Dump of WifiBackupRestore");
        if (mDebugLastBackupDataRetrieved != null) {
            pw.println("Last backup data retrieved: "
                    + createLogFromBackupData(mDebugLastBackupDataRetrieved));
        }
        if (mDebugLastBackupDataRestored != null) {
            pw.println("Last backup data restored: "
                    + createLogFromBackupData(mDebugLastBackupDataRestored));
        }
        if (mDebugLastSupplicantBackupDataRestored != null) {
            pw.println("Last old supplicant backup data restored: "
                    + SupplicantBackupMigration.createLogFromBackupData(
                            mDebugLastSupplicantBackupDataRestored));
        }
        if (mDebugLastIpConfigBackupDataRestored != null) {
            pw.println("Last old ipconfig backup data restored: "
                    + mDebugLastIpConfigBackupDataRestored);
        }
    }

    /**
     * These sub classes contain the logic to parse older backups and restore wifi state from it.
     * Most of the code here has been migrated over from BackupSettingsAgent.
     * This is kind of ugly text parsing, but it is needed to support the migration of this data.
     */
    public static class SupplicantBackupMigration {
        /**
         * List of keys to look out for in wpa_supplicant.conf parsing.
         * These key values are declared in different parts of the wifi codebase today.
         */
        public static final String SUPPLICANT_KEY_SSID = WifiConfiguration.ssidVarName;
        public static final String SUPPLICANT_KEY_HIDDEN = WifiConfiguration.hiddenSSIDVarName;
        public static final String SUPPLICANT_KEY_KEY_MGMT = WifiConfiguration.KeyMgmt.varName;
        public static final String SUPPLICANT_KEY_AUTH_ALG =
                WifiConfiguration.AuthAlgorithm.varName;
        public static final String SUPPLICANT_KEY_CLIENT_CERT =
                WifiEnterpriseConfig.CLIENT_CERT_KEY;
        public static final String SUPPLICANT_KEY_CA_CERT = WifiEnterpriseConfig.CA_CERT_KEY;
        public static final String SUPPLICANT_KEY_CA_PATH = WifiEnterpriseConfig.CA_PATH_KEY;
        public static final String SUPPLICANT_KEY_EAP = WifiEnterpriseConfig.EAP_KEY;
        public static final String SUPPLICANT_KEY_PSK = WifiConfiguration.pskVarName;
        public static final String SUPPLICANT_KEY_WEP_KEY0 = WifiConfiguration.wepKeyVarNames[0];
        public static final String SUPPLICANT_KEY_WEP_KEY1 = WifiConfiguration.wepKeyVarNames[1];
        public static final String SUPPLICANT_KEY_WEP_KEY2 = WifiConfiguration.wepKeyVarNames[2];
        public static final String SUPPLICANT_KEY_WEP_KEY3 = WifiConfiguration.wepKeyVarNames[3];
        public static final String SUPPLICANT_KEY_WEP_KEY_IDX =
                WifiConfiguration.wepTxKeyIdxVarName;
        public static final String SUPPLICANT_KEY_ID_STR = "id_str";

        /**
         * Regex to mask out passwords in backup data dump.
         */
        private static final String PSK_MASK_LINE_MATCH_PATTERN =
                ".*" + SUPPLICANT_KEY_PSK + ".*=.*";
        private static final String PSK_MASK_SEARCH_PATTERN =
                "(.*" + SUPPLICANT_KEY_PSK + ".*=)(.*)";
        private static final String PSK_MASK_REPLACE_PATTERN = "$1*";

        private static final String WEP_KEYS_MASK_LINE_MATCH_PATTERN =
                ".*" + SUPPLICANT_KEY_WEP_KEY0.replace("0", "") + ".*=.*";
        private static final String WEP_KEYS_MASK_SEARCH_PATTERN =
                "(.*" + SUPPLICANT_KEY_WEP_KEY0.replace("0", "") + ".*=)(.*)";
        private static final String WEP_KEYS_MASK_REPLACE_PATTERN = "$1*";

        /**
         * Create log dump of the backup data in wpa_supplicant.conf format with the preShared &
         * WEP key masked.
         *
         * PSK keys are written in the following format in wpa_supplicant.conf:
         *  psk=WifiBackupRestorePsk
         *
         * WEP Keys are written in following format in wpa_supplicant.conf:
         *  wep_keys0=WifiBackupRestoreWep0
         *  wep_keys1=WifiBackupRestoreWep1
         *  wep_keys2=WifiBackupRestoreWep2
         *  wep_keys3=WifiBackupRestoreWep3
         */
        public static String createLogFromBackupData(byte[] data) {
            StringBuilder sb = new StringBuilder();
            try {
                String supplicantConfString = new String(data, StandardCharsets.UTF_8.name());
                for (String line : supplicantConfString.split("\n")) {
                    if (line.matches(PSK_MASK_LINE_MATCH_PATTERN)) {
                        line = line.replaceAll(PSK_MASK_SEARCH_PATTERN, PSK_MASK_REPLACE_PATTERN);
                    }
                    if (line.matches(WEP_KEYS_MASK_LINE_MATCH_PATTERN)) {
                        line = line.replaceAll(
                                WEP_KEYS_MASK_SEARCH_PATTERN, WEP_KEYS_MASK_REPLACE_PATTERN);
                    }
                    sb.append(line).append("\n");
                }
            } catch (UnsupportedEncodingException e) {
                return "";
            }
            return sb.toString();
        }

        /**
         * Class for capturing a network definition from the wifi supplicant config file.
         */
        static class SupplicantNetwork {
            private String mParsedSSIDLine;
            private String mParsedHiddenLine;
            private String mParsedKeyMgmtLine;
            private String mParsedAuthAlgLine;
            private String mParsedPskLine;
            private String[] mParsedWepKeyLines = new String[4];
            private String mParsedWepTxKeyIdxLine;
            private String mParsedIdStrLine;
            public boolean certUsed = false;
            public boolean isEap = false;

            /**
             * Read lines from wpa_supplicant.conf stream for this network.
             */
            public static SupplicantNetwork readNetworkFromStream(BufferedReader in) {
                final SupplicantNetwork n = new SupplicantNetwork();
                String line;
                try {
                    while (in.ready()) {
                        line = in.readLine();
                        if (line == null || line.startsWith("}")) {
                            break;
                        }
                        n.parseLine(line);
                    }
                } catch (IOException e) {
                    return null;
                }
                return n;
            }

            /**
             * Parse a line from wpa_supplicant.conf stream for this network.
             */
            void parseLine(String line) {
                // Can't rely on particular whitespace patterns so strip leading/trailing.
                line = line.trim();
                if (line.isEmpty()) return; // only whitespace; drop the line.

                // Now parse the network block within wpa_supplicant.conf and store the important
                // lines for processing later.
                if (line.startsWith(SUPPLICANT_KEY_SSID + "=")) {
                    mParsedSSIDLine = line;
                } else if (line.startsWith(SUPPLICANT_KEY_HIDDEN + "=")) {
                    mParsedHiddenLine = line;
                } else if (line.startsWith(SUPPLICANT_KEY_KEY_MGMT + "=")) {
                    mParsedKeyMgmtLine = line;
                    if (line.contains("EAP")) {
                        isEap = true;
                    }
                } else if (line.startsWith(SUPPLICANT_KEY_AUTH_ALG + "=")) {
                    mParsedAuthAlgLine = line;
                } else if (line.startsWith(SUPPLICANT_KEY_CLIENT_CERT + "=")) {
                    certUsed = true;
                } else if (line.startsWith(SUPPLICANT_KEY_CA_CERT + "=")) {
                    certUsed = true;
                } else if (line.startsWith(SUPPLICANT_KEY_CA_PATH + "=")) {
                    certUsed = true;
                } else if (line.startsWith(SUPPLICANT_KEY_EAP + "=")) {
                    isEap = true;
                } else if (line.startsWith(SUPPLICANT_KEY_PSK + "=")) {
                    mParsedPskLine = line;
                } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY0 + "=")) {
                    mParsedWepKeyLines[0] = line;
                } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY1 + "=")) {
                    mParsedWepKeyLines[1] = line;
                } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY2 + "=")) {
                    mParsedWepKeyLines[2] = line;
                } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY3 + "=")) {
                    mParsedWepKeyLines[3] = line;
                } else if (line.startsWith(SUPPLICANT_KEY_WEP_KEY_IDX + "=")) {
                    mParsedWepTxKeyIdxLine = line;
                } else if (line.startsWith(SUPPLICANT_KEY_ID_STR + "=")) {
                    mParsedIdStrLine = line;
                }
            }

            /**
             * Create WifiConfiguration object from the parsed data for this network.
             */
            public WifiConfiguration createWifiConfiguration() {
                if (mParsedSSIDLine == null) {
                    // No SSID => malformed network definition
                    return null;
                }
                WifiConfiguration configuration = new WifiConfiguration();
                configuration.SSID = mParsedSSIDLine.substring(mParsedSSIDLine.indexOf('=') + 1);

                if (mParsedHiddenLine != null) {
                    // Can't use Boolean.valueOf() because it works only for true/false.
                    configuration.hiddenSSID =
                            Integer.parseInt(mParsedHiddenLine.substring(
                                    mParsedHiddenLine.indexOf('=') + 1)) != 0;
                }
                if (mParsedKeyMgmtLine == null) {
                    // no key_mgmt line specified; this is defined as equivalent to
                    // "WPA-PSK WPA-EAP".
                    configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
                    configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
                } else {
                    // Need to parse the mParsedKeyMgmtLine line
                    final String bareKeyMgmt =
                            mParsedKeyMgmtLine.substring(mParsedKeyMgmtLine.indexOf('=') + 1);
                    String[] typeStrings = bareKeyMgmt.split("\\s+");

                    // Parse out all the key management regimes permitted for this network.
                    // The literal strings here are the standard values permitted in
                    // wpa_supplicant.conf.
                    for (int i = 0; i < typeStrings.length; i++) {
                        final String ktype = typeStrings[i];
                        if (ktype.equals("NONE")) {
                            configuration.allowedKeyManagement.set(
                                    WifiConfiguration.KeyMgmt.NONE);
                        } else if (ktype.equals("WPA-PSK")) {
                            configuration.allowedKeyManagement.set(
                                    WifiConfiguration.KeyMgmt.WPA_PSK);
                        } else if (ktype.equals("WPA-EAP")) {
                            configuration.allowedKeyManagement.set(
                                    WifiConfiguration.KeyMgmt.WPA_EAP);
                        } else if (ktype.equals("IEEE8021X")) {
                            configuration.allowedKeyManagement.set(
                                    WifiConfiguration.KeyMgmt.IEEE8021X);
                        } else if (ktype.equals("WAPI-PSK")) {
                            configuration.allowedKeyManagement.set(
                                    WifiConfiguration.KeyMgmt.WAPI_PSK);
                        } else if (ktype.equals("WAPI-CERT")) {
                            configuration.allowedKeyManagement.set(
                                    WifiConfiguration.KeyMgmt.WAPI_CERT);
                        }
                    }
                }
                if (mParsedAuthAlgLine != null) {
                    if (mParsedAuthAlgLine.contains("OPEN")) {
                        configuration.allowedAuthAlgorithms.set(
                                WifiConfiguration.AuthAlgorithm.OPEN);
                    }
                    if (mParsedAuthAlgLine.contains("SHARED")) {
                        configuration.allowedAuthAlgorithms.set(
                                WifiConfiguration.AuthAlgorithm.SHARED);
                    }
                }
                if (mParsedPskLine != null) {
                    configuration.preSharedKey =
                            mParsedPskLine.substring(mParsedPskLine.indexOf('=') + 1);
                }
                if (mParsedWepKeyLines[0] != null) {
                    configuration.wepKeys[0] =
                            mParsedWepKeyLines[0].substring(mParsedWepKeyLines[0].indexOf('=') + 1);
                }
                if (mParsedWepKeyLines[1] != null) {
                    configuration.wepKeys[1] =
                            mParsedWepKeyLines[1].substring(mParsedWepKeyLines[1].indexOf('=') + 1);
                }
                if (mParsedWepKeyLines[2] != null) {
                    configuration.wepKeys[2] =
                            mParsedWepKeyLines[2].substring(mParsedWepKeyLines[2].indexOf('=') + 1);
                }
                if (mParsedWepKeyLines[3] != null) {
                    configuration.wepKeys[3] =
                            mParsedWepKeyLines[3].substring(mParsedWepKeyLines[3].indexOf('=') + 1);
                }
                if (mParsedWepTxKeyIdxLine != null) {
                    configuration.wepTxKeyIndex =
                            Integer.valueOf(mParsedWepTxKeyIdxLine.substring(
                                    mParsedWepTxKeyIdxLine.indexOf('=') + 1));
                }
                if (mParsedIdStrLine != null) {
                    String idString =
                            mParsedIdStrLine.substring(mParsedIdStrLine.indexOf('=') + 1);
                    if (idString != null) {
                        Map<String, String> extras =
                                SupplicantStaNetworkHal.parseNetworkExtra(
                                        NativeUtil.removeEnclosingQuotes(idString));
                        if (extras == null) {
                            Log.e(TAG, "Error parsing network extras, ignoring network.");
                            return null;
                        }
                        String configKey = extras.get(
                                SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY);
                        // No ConfigKey was passed but we need it for validating the parsed
                        // network so we stop the restore.
                        if (configKey == null) {
                            Log.e(TAG, "Configuration key was not passed, ignoring network.");
                            return null;
                        }
                        if (!configKey.equals(configuration.getKey())) {
                            // ConfigKey mismatches are expected for private networks because the
                            // UID is not preserved across backup/restore.
                            Log.w(TAG, "Configuration key does not match. Retrieved: " + configKey
                                    + ", Calculated: " + configuration.getKey());
                        }
                        // For wpa_supplicant backup data, parse out the creatorUid to ensure that
                        // these networks were created by system apps.
                        int creatorUid =
                                Integer.parseInt(extras.get(
                                        SupplicantStaNetworkHal.ID_STRING_KEY_CREATOR_UID));
                        if (creatorUid >= Process.FIRST_APPLICATION_UID) {
                            Log.d(TAG, "Ignoring network from non-system app: "
                                    + configuration.getKey());
                            return null;
                        }
                    }
                }
                return configuration;
            }
        }

        /**
         * Ingest multiple wifi config fragments from wpa_supplicant.conf, looking for network={}
         * blocks and eliminating duplicates
         */
        static class SupplicantNetworks {
            final ArrayList<SupplicantNetwork> mNetworks = new ArrayList<>(8);

            /**
             * Parse the wpa_supplicant.conf file stream and add networks.
             */
            public void readNetworksFromStream(BufferedReader in) {
                try {
                    String line;
                    while (in.ready()) {
                        line = in.readLine();
                        if (line != null) {
                            if (line.startsWith("network")) {
                                SupplicantNetwork net = SupplicantNetwork.readNetworkFromStream(in);

                                // An IOException occurred while trying to read the network.
                                if (net == null) {
                                    Log.e(TAG, "Error while parsing the network.");
                                    continue;
                                }

                                // Networks that use certificates for authentication can't be
                                // restored because the certificates they need don't get restored
                                // (because they are stored in keystore, and can't be restored).
                                // Similarly, omit EAP network definitions to avoid propagating
                                // controlled enterprise network definitions.
                                if (net.isEap || net.certUsed) {
                                    Log.d(TAG, "Skipping enterprise network for restore: "
                                            + net.mParsedSSIDLine + " / " + net.mParsedKeyMgmtLine);
                                    continue;
                                }
                                mNetworks.add(net);
                            }
                        }
                    }
                } catch (IOException e) {
                    // whatever happened, we're done now
                }
            }

            /**
             * Retrieve a list of WifiConfiguration objects parsed from wpa_supplicant.conf
             */
            public List<WifiConfiguration> retrieveWifiConfigurations() {
                ArrayList<WifiConfiguration> wifiConfigurations = new ArrayList<>();
                for (SupplicantNetwork net : mNetworks) {
                    try {
                        WifiConfiguration wifiConfiguration = net.createWifiConfiguration();
                        if (wifiConfiguration != null) {
                            Log.v(TAG, "Parsed Configuration: " + wifiConfiguration.getKey());
                            wifiConfigurations.add(wifiConfiguration);
                        }
                    } catch (NumberFormatException e) {
                        // Occurs if we are unable to parse the hidden SSID, WEP Key index or
                        // creator UID.
                        Log.e(TAG, "Error parsing wifi configuration: " + e);
                        return null;
                    }
                }
                return wifiConfigurations;
            }
        }
    }
}
