/*
 * Copyright (C) 2010, 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.connectivitymanagertest;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
import android.util.Log;

import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


/**
 * Help class to process configurations of access points saved in an XML file.
 * The configurations of an access point is included in tag
 * <accesspoint></accesspoint>. The supported configuration includes: ssid,
 * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
 * in which each is included in the corresponding tags. Static IP setting is also supported.
 * Tags that can be used include: ip, gateway, networkprefixlength, dns1, dns2. All access points
 * have to be enclosed in tags of <resources></resources>.
 *
 * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
 * <resources>
 *   <accesspoint>
 *   <ssid>testnet</ssid>
 *   <security>EAP</security>
 *   <eap>PEAP</eap>
 *   <phase2>MSCHAP2</phase2>
 *   <identity>donut</identity</identity>
 *   <password>abcdefgh</password>
 *   </accesspoint>
 * </resources>
 *
 * Note:ssid and security have to be the first two tags
 *      for static ip setting, tag "ip" should be listed before other fields: dns, gateway,
 *      networkprefixlength.
 */
public class AccessPointParserHelper {
    private static final String KEYSTORE_SPACE = "keystore://";
    private static final String TAG = "AccessPointParserHelper";
    static final int NONE = 0;
    static final int WEP = 1;
    static final int PSK = 2;
    static final int EAP = 3;

    List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();

    private int getSecurityType (String security) {
        if (security.equalsIgnoreCase("NONE")) {
            return NONE;
        } else if (security.equalsIgnoreCase("WEP")) {
            return WEP;
        } else if (security.equalsIgnoreCase("PSK")) {
            return PSK;
        } else if (security.equalsIgnoreCase("EAP")) {
            return EAP;
        } else {
            return -1;
        }
    }

    private boolean validateEapValue(String value) {
        if (value.equalsIgnoreCase("PEAP") ||
                value.equalsIgnoreCase("TLS") ||
                value.equalsIgnoreCase("TTLS")) {
            return true;
        } else {
            return false;
        }
    }

    DefaultHandler mHandler = new DefaultHandler() {

        boolean ssid = false;
        boolean security = false;
        boolean password = false;
        boolean ip = false;
        boolean gateway = false;
        boolean networkprefix = false;
        boolean dns1 = false;
        boolean dns2 = false;
        boolean eap = false;
        boolean phase2 = false;
        boolean identity = false;
        boolean anonymousidentity = false;
        boolean cacert = false;
        boolean usercert = false;
        WifiConfiguration config = null;
        int securityType = NONE;
        LinkProperties mLinkProperties = null;
        InetAddress mInetAddr = null;

        @Override
        public void startElement(String uri, String localName, String tagName,
                Attributes attributes) throws SAXException {
            if (tagName.equalsIgnoreCase("accesspoint")) {
                config = new WifiConfiguration();
            }
            if (tagName.equalsIgnoreCase("ssid")) {
                ssid = true;
            }
            if (tagName.equalsIgnoreCase("security")) {
                security = true;
            }
            if (tagName.equalsIgnoreCase("password")) {
                password = true;
            }
            if (tagName.equalsIgnoreCase("eap")) {
                eap = true;
            }
            if (tagName.equalsIgnoreCase("phase2")) {
                phase2 = true;
            }
            if (tagName.equalsIgnoreCase("identity")) {
                identity = true;
            }
            if (tagName.equalsIgnoreCase("anonymousidentity")) {
                anonymousidentity = true;
            }
            if (tagName.equalsIgnoreCase("cacert")) {
                cacert = true;
            }
            if (tagName.equalsIgnoreCase("usercert")) {
                usercert = true;
            }
            if (tagName.equalsIgnoreCase("ip")) {
                mLinkProperties = new LinkProperties();
                ip = true;
            }
            if (tagName.equalsIgnoreCase("gateway")) {
                gateway = true;
            }
            if (tagName.equalsIgnoreCase("networkprefixlength")) {
                networkprefix = true;
            }
            if (tagName.equalsIgnoreCase("dns1")) {
                dns1 = true;
            }
            if (tagName.equalsIgnoreCase("dns2")) {
                dns2 = true;
            }
        }

        @Override
        public void endElement(String uri, String localName, String tagName) throws SAXException {
            if (tagName.equalsIgnoreCase("accesspoint")) {
                if (mLinkProperties != null) {
                    config.ipAssignment = IpAssignment.STATIC;
                    config.linkProperties = mLinkProperties;
                } else {
                    config.ipAssignment = IpAssignment.DHCP;
                }
                config.proxySettings = ProxySettings.NONE;
                networks.add(config);
                mLinkProperties = null;
            }
        }

        @Override
        public void characters(char ch[], int start, int length) throws SAXException {
            if (ssid) {
                config.SSID = new String(ch, start, length);
                ssid = false;
            }
            if (security) {
                String securityStr = (new String(ch, start, length)).toUpperCase();
                securityType = getSecurityType(securityStr);
                switch (securityType) {
                    case NONE:
                        config.allowedKeyManagement.set(KeyMgmt.NONE);
                        break;
                    case WEP:
                        config.allowedKeyManagement.set(KeyMgmt.NONE);
                        config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
                        config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
                        break;
                    case PSK:
                        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
                        break;
                    case EAP:
                        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
                        config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
                        // Initialize other fields.
                        config.phase2.setValue("");
                        config.ca_cert.setValue("");
                        config.client_cert.setValue("");
                        config.engine.setValue("");
                        config.engine_id.setValue("");
                        config.key_id.setValue("");
                        config.identity.setValue("");
                        config.anonymous_identity.setValue("");
                        break;
                    default:
                        throw new SAXException();
                }
                security = false;
            }
            if (password) {
                String passwordStr = new String(ch, start, length);
                int len = passwordStr.length();
                if (len == 0) {
                    throw new SAXException();
                }
                if (securityType == WEP) {
                    if ((len == 10 || len == 26 || len == 58) &&
                            passwordStr.matches("[0-9A-Fa-f]*")) {
                        config.wepKeys[0] = passwordStr;
                    } else {
                        config.wepKeys[0] = '"' + passwordStr + '"';
                    }
                } else if (securityType == PSK) {
                    if (passwordStr.matches("[0-9A-Fa-f]{64}")) {
                        config.preSharedKey = passwordStr;
                    } else {
                        config.preSharedKey = '"' + passwordStr + '"';
                    }
                } else if (securityType == EAP) {
                    config.password.setValue(passwordStr);
                } else {
                    throw new SAXException();
                }
                password = false;
            }
            if (eap) {
                String eapValue = new String(ch, start, length);
                if (!validateEapValue(eapValue)) {
                    throw new SAXException();
                }
                config.eap.setValue(eapValue);
                eap = false;
            }
            if (phase2) {
                String phase2Value = new String(ch, start, length);
                config.phase2.setValue("auth=" + phase2Value);
                phase2 = false;
            }
            if (identity) {
                String identityValue = new String(ch, start, length);
                config.identity.setValue(identityValue);
                identity = false;
            }
            if (anonymousidentity) {
                String anonyId = new String(ch, start, length);
                config.anonymous_identity.setValue(anonyId);
                anonymousidentity = false;
            }
            if (cacert) {
                String cacertValue = new String(ch, start, length);
                // need to install the credentail to "keystore://"
                config.ca_cert.setValue(KEYSTORE_SPACE);
                cacert = false;
            }
            if (usercert) {
                String usercertValue = new String(ch, start, length);
                config.client_cert.setValue(KEYSTORE_SPACE);
                usercert = false;
            }
            if (ip) {
                try {
                    String ipAddr = new String(ch, start, length);
                    if (!InetAddress.isNumeric(ipAddr)) {
                        throw new SAXException();
                    }
                    mInetAddr = InetAddress.getByName(ipAddr);
                } catch (UnknownHostException e) {
                    throw new SAXException();
                }
                ip = false;
            }
            if (gateway) {
                try {
                    String gwAddr = new String(ch, start, length);
                    if (!InetAddress.isNumeric(gwAddr)) {
                        throw new SAXException();
                    }
                    mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr)));
                } catch (UnknownHostException e) {
                    throw new SAXException();
                }
                gateway = false;
            }
            if (networkprefix) {
                try {
                    int nwPrefixLength = Integer.parseInt(new String(ch, start, length));
                    if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) {
                        throw new SAXException();
                    }
                    mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, nwPrefixLength));
                } catch (NumberFormatException e) {
                    throw new SAXException();
                }
                networkprefix = false;
            }
            if (dns1) {
                try {
                    String dnsAddr = new String(ch, start, length);
                    if (!InetAddress.isNumeric(dnsAddr)) {
                        throw new SAXException();
                    }
                    mLinkProperties.addDns(InetAddress.getByName(dnsAddr));
                } catch (UnknownHostException e) {
                    throw new SAXException();
                }
                dns1 = false;
            }
            if (dns2) {
                try {
                    String dnsAddr = new String(ch, start, length);
                    if (!InetAddress.isNumeric(dnsAddr)) {
                        throw new SAXException();
                    }
                    mLinkProperties.addDns(InetAddress.getByName(dnsAddr));
                } catch (UnknownHostException e) {
                    throw new SAXException();
                }
                dns2 = false;
            }
        }
    };

    /**
     * Process the InputStream in
     * @param in is the InputStream that can be used for XML parsing
     * @throws Exception
     */
    public AccessPointParserHelper(InputStream in) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser saxParser = factory.newSAXParser();
        saxParser.parse(in, mHandler);
    }

    public List<WifiConfiguration> getNetworkConfigurations() throws Exception {
        return networks;
    }
}
