/* 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.exchange.adapter;

import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.storage.StorageManager;

import com.android.emailcommon.provider.Policy;
import com.android.exchange.EasSyncService;
import com.android.exchange.R;
import com.android.exchange.service.EasAccountValidator;
import com.android.mail.utils.LogUtils;

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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * Parse the result of the Provision command
 */
public class ProvisionParser extends Parser {
    private static final String TAG = "ProvisionParser";

    private final Context mContext;
    private Policy mPolicy = null;
    private String mSecuritySyncKey = null;
    private boolean mRemoteWipe = false;
    private boolean mIsSupportable = true;
    private boolean smimeRequired = false;
    private final Resources mResources;

    public ProvisionParser(final Context context, final InputStream in) throws IOException {
        super(in);
        mContext = context;
        mResources = context.getResources();
    }

    public Policy getPolicy() {
        return mPolicy;
    }

    public String getSecuritySyncKey() {
        return mSecuritySyncKey;
    }

    public void setSecuritySyncKey(String securitySyncKey) {
        mSecuritySyncKey = securitySyncKey;
    }

    public boolean getRemoteWipe() {
        return mRemoteWipe;
    }

    public boolean hasSupportablePolicySet() {
        return (mPolicy != null) && mIsSupportable;
    }

    public void clearUnsupportablePolicies() {
        mIsSupportable = true;
        mPolicy.mProtocolPoliciesUnsupported = null;
    }

    private void addPolicyString(StringBuilder sb, int res) {
        sb.append(mResources.getString(res));
        sb.append(Policy.POLICY_STRING_DELIMITER);
    }

    /**
     * Complete setup of a Policy; we normalize it first (removing inconsistencies, etc.) and then
     * generate the tokenized "protocol policies enforced" string.  Note that unsupported policies
     * must have been added prior to calling this method (this is only a possibility with wbxml
     * policy documents, as all versions of the OS support the policies in xml documents).
     */
    private void setPolicy(Policy policy) {
        policy.normalize();
        StringBuilder sb = new StringBuilder();
        if (policy.mDontAllowAttachments) {
            addPolicyString(sb, R.string.policy_dont_allow_attachments);
        }
        if (policy.mRequireManualSyncWhenRoaming) {
            addPolicyString(sb, R.string.policy_require_manual_sync_roaming);
        }
        policy.mProtocolPoliciesEnforced = sb.toString();
        mPolicy = policy;
    }

    private boolean deviceSupportsEncryption() {
        DevicePolicyManager dpm =
                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
        int status = dpm.getStorageEncryptionStatus();
        return status != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
    }

    private void parseProvisionDocWbxml() throws IOException {
        Policy policy = new Policy();
        ArrayList<Integer> unsupportedList = new ArrayList<Integer>();
        boolean passwordEnabled = false;

        while (nextTag(Tags.PROVISION_EAS_PROVISION_DOC) != END) {
            boolean tagIsSupported = true;
            int res = 0;
            switch (tag) {
                case Tags.PROVISION_DEVICE_PASSWORD_ENABLED:
                    if (getValueInt() == 1) {
                        passwordEnabled = true;
                        if (policy.mPasswordMode == Policy.PASSWORD_MODE_NONE) {
                            policy.mPasswordMode = Policy.PASSWORD_MODE_SIMPLE;
                        }
                    }
                    break;
                case Tags.PROVISION_MIN_DEVICE_PASSWORD_LENGTH:
                    policy.mPasswordMinLength = getValueInt();
                    break;
                case Tags.PROVISION_ALPHA_DEVICE_PASSWORD_ENABLED:
                    if (getValueInt() == 1) {
                        policy.mPasswordMode = Policy.PASSWORD_MODE_STRONG;
                    }
                    break;
                case Tags.PROVISION_MAX_INACTIVITY_TIME_DEVICE_LOCK:
                    // EAS gives us seconds, which is, happily, what the PolicySet requires
                    policy.mMaxScreenLockTime = getValueInt();
                    break;
                case Tags.PROVISION_MAX_DEVICE_PASSWORD_FAILED_ATTEMPTS:
                    policy.mPasswordMaxFails = getValueInt();
                    break;
                case Tags.PROVISION_DEVICE_PASSWORD_EXPIRATION:
                    policy.mPasswordExpirationDays = getValueInt();
                    break;
                case Tags.PROVISION_DEVICE_PASSWORD_HISTORY:
                    policy.mPasswordHistory = getValueInt();
                    break;
                case Tags.PROVISION_ALLOW_CAMERA:
                    policy.mDontAllowCamera = (getValueInt() == 0);
                    break;
                case Tags.PROVISION_ALLOW_SIMPLE_DEVICE_PASSWORD:
                    // Ignore this unless there's any MSFT documentation for what this means
                    // Hint: I haven't seen any that's more specific than "simple"
                    getValue();
                    break;
                // The following policies, if false, can't be supported at the moment
                case Tags.PROVISION_ALLOW_STORAGE_CARD:
                case Tags.PROVISION_ALLOW_UNSIGNED_APPLICATIONS:
                case Tags.PROVISION_ALLOW_UNSIGNED_INSTALLATION_PACKAGES:
                case Tags.PROVISION_ALLOW_WIFI:
                case Tags.PROVISION_ALLOW_TEXT_MESSAGING:
                case Tags.PROVISION_ALLOW_POP_IMAP_EMAIL:
                case Tags.PROVISION_ALLOW_IRDA:
                case Tags.PROVISION_ALLOW_HTML_EMAIL:
                case Tags.PROVISION_ALLOW_BROWSER:
                case Tags.PROVISION_ALLOW_CONSUMER_EMAIL:
                case Tags.PROVISION_ALLOW_INTERNET_SHARING:
                    if (getValueInt() == 0) {
                        tagIsSupported = false;
                        switch(tag) {
                            case Tags.PROVISION_ALLOW_STORAGE_CARD:
                                res = R.string.policy_dont_allow_storage_cards;
                                break;
                            case Tags.PROVISION_ALLOW_UNSIGNED_APPLICATIONS:
                                res = R.string.policy_dont_allow_unsigned_apps;
                                break;
                            case Tags.PROVISION_ALLOW_UNSIGNED_INSTALLATION_PACKAGES:
                                res = R.string.policy_dont_allow_unsigned_installers;
                                break;
                            case Tags.PROVISION_ALLOW_WIFI:
                                res = R.string.policy_dont_allow_wifi;
                                break;
                            case Tags.PROVISION_ALLOW_TEXT_MESSAGING:
                                res = R.string.policy_dont_allow_text_messaging;
                                break;
                            case Tags.PROVISION_ALLOW_POP_IMAP_EMAIL:
                                res = R.string.policy_dont_allow_pop_imap;
                                break;
                            case Tags.PROVISION_ALLOW_IRDA:
                                res = R.string.policy_dont_allow_irda;
                                break;
                            case Tags.PROVISION_ALLOW_HTML_EMAIL:
                                res = R.string.policy_dont_allow_html;
                                policy.mDontAllowHtml = true;
                                break;
                            case Tags.PROVISION_ALLOW_BROWSER:
                                res = R.string.policy_dont_allow_browser;
                                break;
                            case Tags.PROVISION_ALLOW_CONSUMER_EMAIL:
                                res = R.string.policy_dont_allow_consumer_email;
                                break;
                            case Tags.PROVISION_ALLOW_INTERNET_SHARING:
                                res = R.string.policy_dont_allow_internet_sharing;
                                break;
                        }
                        if (res > 0) {
                            unsupportedList.add(res);
                        }
                    }
                    break;
                case Tags.PROVISION_ATTACHMENTS_ENABLED:
                    policy.mDontAllowAttachments = getValueInt() != 1;
                    break;
                // Bluetooth: 0 = no bluetooth; 1 = only hands-free; 2 = allowed
                case Tags.PROVISION_ALLOW_BLUETOOTH:
                    if (getValueInt() != 2) {
                        tagIsSupported = false;
                        unsupportedList.add(R.string.policy_bluetooth_restricted);
                    }
                    break;
                // We may now support device (internal) encryption; we'll check this capability
                // below with the call to SecurityPolicy.isSupported()
                case Tags.PROVISION_REQUIRE_DEVICE_ENCRYPTION:
                    if (getValueInt() == 1) {
                         if (!deviceSupportsEncryption()) {
                            tagIsSupported = false;
                            unsupportedList.add(R.string.policy_require_encryption);
                        } else {
                            policy.mRequireEncryption = true;
                        }
                    }
                    break;
                // Note that DEVICE_ENCRYPTION_ENABLED refers to SD card encryption, which the OS
                // does not yet support.
                case Tags.PROVISION_DEVICE_ENCRYPTION_ENABLED:
                    if (getValueInt() == 1) {
                        log("Policy requires SD card encryption");
                        // Let's see if this can be supported on our device...
                        if (deviceSupportsEncryption()) {
                            // NOTE: Private API!
                            // Go through volumes; if ANY are removable, we can't support this
                            // policy.
                            tagIsSupported = !hasRemovableStorage();
                            if (tagIsSupported) {
                                // If this policy is requested, we MUST also require encryption
                                log("Device supports SD card encryption");
                                policy.mRequireEncryption = true;
                                break;
                            }
                        } else {
                            log("Device doesn't support encryption; failing");
                            tagIsSupported = false;
                        }
                        // If we fall through, we can't support the policy
                        unsupportedList.add(R.string.policy_require_sd_encryption);
                    }
                    break;
                    // Note this policy; we enforce it in ExchangeService
                case Tags.PROVISION_REQUIRE_MANUAL_SYNC_WHEN_ROAMING:
                    policy.mRequireManualSyncWhenRoaming = getValueInt() == 1;
                    break;
                // We are allowed to accept policies, regardless of value of this tag
                // TODO: When we DO support a recovery password, we need to store the value in
                // the account (so we know to utilize it)
                case Tags.PROVISION_PASSWORD_RECOVERY_ENABLED:
                    // Read, but ignore, value
                    policy.mPasswordRecoveryEnabled = getValueInt() == 1;
                    break;
                // The following policies, if true, can't be supported at the moment
                case Tags.PROVISION_REQUIRE_SIGNED_SMIME_MESSAGES:
                case Tags.PROVISION_REQUIRE_ENCRYPTED_SMIME_MESSAGES:
                case Tags.PROVISION_REQUIRE_SIGNED_SMIME_ALGORITHM:
                case Tags.PROVISION_REQUIRE_ENCRYPTION_SMIME_ALGORITHM:
                    if (getValueInt() == 1) {
                        tagIsSupported = false;
                        if (!smimeRequired) {
                            unsupportedList.add(R.string.policy_require_smime);
                            smimeRequired = true;
                        }
                    }
                    break;
                case Tags.PROVISION_MAX_ATTACHMENT_SIZE:
                    int max = getValueInt();
                    if (max > 0) {
                        policy.mMaxAttachmentSize = max;
                    }
                    break;
                // Complex characters are supported
                case Tags.PROVISION_MIN_DEVICE_PASSWORD_COMPLEX_CHARS:
                    policy.mPasswordComplexChars = getValueInt();
                    break;
                // The following policies are moot; they allow functionality that we don't support
                case Tags.PROVISION_ALLOW_DESKTOP_SYNC:
                case Tags.PROVISION_ALLOW_SMIME_ENCRYPTION_NEGOTIATION:
                case Tags.PROVISION_ALLOW_SMIME_SOFT_CERTS:
                case Tags.PROVISION_ALLOW_REMOTE_DESKTOP:
                    skipTag();
                    break;
                // We don't handle approved/unapproved application lists
                case Tags.PROVISION_UNAPPROVED_IN_ROM_APPLICATION_LIST:
                case Tags.PROVISION_APPROVED_APPLICATION_LIST:
                    // Parse and throw away the content
                    if (specifiesApplications(tag)) {
                        tagIsSupported = false;
                        if (tag == Tags.PROVISION_UNAPPROVED_IN_ROM_APPLICATION_LIST) {
                            unsupportedList.add(R.string.policy_app_blacklist);
                        } else {
                            unsupportedList.add(R.string.policy_app_whitelist);
                        }
                    }
                    break;
                // We accept calendar age, since we never ask for more than two weeks, and that's
                // the most restrictive policy
                case Tags.PROVISION_MAX_CALENDAR_AGE_FILTER:
                    policy.mMaxCalendarLookback = getValueInt();
                    break;
                // We handle max email lookback
                case Tags.PROVISION_MAX_EMAIL_AGE_FILTER:
                    policy.mMaxEmailLookback = getValueInt();
                    break;
                // We currently reject these next two policies
                case Tags.PROVISION_MAX_EMAIL_BODY_TRUNCATION_SIZE:
                case Tags.PROVISION_MAX_EMAIL_HTML_BODY_TRUNCATION_SIZE:
                    String value = getValue();
                    // -1 indicates no required truncation
                    if (!value.equals("-1")) {
                        max = Integer.parseInt(value);
                        if (tag == Tags.PROVISION_MAX_EMAIL_BODY_TRUNCATION_SIZE) {
                            policy.mMaxTextTruncationSize = max;
                            unsupportedList.add(R.string.policy_text_truncation);
                        } else {
                            policy.mMaxHtmlTruncationSize = max;
                            unsupportedList.add(R.string.policy_html_truncation);
                        }
                        tagIsSupported = false;
                    }
                    break;
                default:
                    skipTag();
            }

            if (!tagIsSupported) {
                log("Policy not supported: " + tag);
                mIsSupportable = false;
            }
        }

        // Make sure policy settings are valid; password not enabled trumps other password settings
        if (!passwordEnabled) {
            policy.mPasswordMode = Policy.PASSWORD_MODE_NONE;
        }

        if (!unsupportedList.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (int res: unsupportedList) {
                addPolicyString(sb, res);
            }
            policy.mProtocolPoliciesUnsupported = sb.toString();
        }

        setPolicy(policy);
    }

    /**
     * Return whether or not either of the application list tags specifies any applications
     * @param endTag the tag whose children we're walking through
     * @return whether any applications were specified (by name or by hash)
     * @throws IOException
     */
    private boolean specifiesApplications(int endTag) throws IOException {
        boolean specifiesApplications = false;
        while (nextTag(endTag) != END) {
            switch (tag) {
                case Tags.PROVISION_APPLICATION_NAME:
                case Tags.PROVISION_HASH:
                    specifiesApplications = true;
                    break;
                default:
                    skipTag();
            }
        }
        return specifiesApplications;
    }

    /*package*/ void parseProvisionDocXml(String doc) throws IOException {
        Policy policy = new Policy();

        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new ByteArrayInputStream(doc.getBytes()), "UTF-8");
            int type = parser.getEventType();
            if (type == XmlPullParser.START_DOCUMENT) {
                type = parser.next();
                if (type == XmlPullParser.START_TAG) {
                    String tagName = parser.getName();
                    if (tagName.equals("wap-provisioningdoc")) {
                        parseWapProvisioningDoc(parser, policy);
                    }
                }
            }
        } catch (XmlPullParserException e) {
           throw new IOException();
        }

        setPolicy(policy);
    }

    /**
     * Return true if password is required; otherwise false.
     */
    private boolean parseSecurityPolicy(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
        boolean passwordRequired = true;
        while (true) {
            int type = parser.nextTag();
            if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
                break;
            } else if (type == XmlPullParser.START_TAG) {
                String tagName = parser.getName();
                if (tagName.equals("parm")) {
                    String name = parser.getAttributeValue(null, "name");
                    if (name.equals("4131")) {
                        String value = parser.getAttributeValue(null, "value");
                        if (value.equals("1")) {
                            passwordRequired = false;
                        }
                    }
                }
            }
        }
        return passwordRequired;
    }

    private void parseCharacteristic(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
        boolean enforceInactivityTimer = true;
        while (true) {
            int type = parser.nextTag();
            if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
                break;
            } else if (type == XmlPullParser.START_TAG) {
                if (parser.getName().equals("parm")) {
                    String name = parser.getAttributeValue(null, "name");
                    String value = parser.getAttributeValue(null, "value");
                    if (name.equals("AEFrequencyValue")) {
                        if (enforceInactivityTimer) {
                            if (value.equals("0")) {
                                policy.mMaxScreenLockTime = 1;
                            } else {
                                policy.mMaxScreenLockTime = 60*Integer.parseInt(value);
                            }
                        }
                    } else if (name.equals("AEFrequencyType")) {
                        // "0" here means we don't enforce an inactivity timeout
                        if (value.equals("0")) {
                            enforceInactivityTimer = false;
                        }
                    } else if (name.equals("DeviceWipeThreshold")) {
                        policy.mPasswordMaxFails = Integer.parseInt(value);
                    } else if (name.equals("CodewordFrequency")) {
                        // Ignore; has no meaning for us
                    } else if (name.equals("MinimumPasswordLength")) {
                        policy.mPasswordMinLength = Integer.parseInt(value);
                    } else if (name.equals("PasswordComplexity")) {
                        if (value.equals("0")) {
                            policy.mPasswordMode = Policy.PASSWORD_MODE_STRONG;
                        } else {
                            policy.mPasswordMode = Policy.PASSWORD_MODE_SIMPLE;
                        }
                    }
                }
            }
        }
    }

    private void parseRegistry(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
      while (true) {
          int type = parser.nextTag();
          if (type == XmlPullParser.END_TAG && parser.getName().equals("characteristic")) {
              break;
          } else if (type == XmlPullParser.START_TAG) {
              String name = parser.getName();
              if (name.equals("characteristic")) {
                  parseCharacteristic(parser, policy);
              }
          }
      }
    }

    private void parseWapProvisioningDoc(XmlPullParser parser, Policy policy)
            throws XmlPullParserException, IOException {
        while (true) {
            int type = parser.nextTag();
            if (type == XmlPullParser.END_TAG && parser.getName().equals("wap-provisioningdoc")) {
                break;
            } else if (type == XmlPullParser.START_TAG) {
                String name = parser.getName();
                if (name.equals("characteristic")) {
                    String atype = parser.getAttributeValue(null, "type");
                    if (atype.equals("SecurityPolicy")) {
                        // If a password isn't required, stop here
                        if (!parseSecurityPolicy(parser, policy)) {
                            return;
                        }
                    } else if (atype.equals("Registry")) {
                        parseRegistry(parser, policy);
                        return;
                    }
                }
            }
        }
    }

    private void parseProvisionData() throws IOException {
        while (nextTag(Tags.PROVISION_DATA) != END) {
            if (tag == Tags.PROVISION_EAS_PROVISION_DOC) {
                parseProvisionDocWbxml();
            } else {
                skipTag();
            }
        }
    }

    private void parsePolicy() throws IOException {
        String policyType = null;
        while (nextTag(Tags.PROVISION_POLICY) != END) {
            switch (tag) {
                case Tags.PROVISION_POLICY_TYPE:
                    policyType = getValue();
                    LogUtils.i(TAG, "Policy type: %s", policyType);
                    break;
                case Tags.PROVISION_POLICY_KEY:
                    mSecuritySyncKey = getValue();
                    break;
                case Tags.PROVISION_STATUS:
                    LogUtils.i(TAG, "Policy status: %s", getValue());
                    break;
                case Tags.PROVISION_DATA:
                    if (policyType.equalsIgnoreCase(EasAccountValidator.EAS_2_POLICY_TYPE)) {
                        // Parse the old style XML document
                        parseProvisionDocXml(getValue());
                    } else {
                        // Parse the newer WBXML data
                        parseProvisionData();
                    }
                    break;
                default:
                    skipTag();
            }
        }
    }

    private void parsePolicies() throws IOException {
        while (nextTag(Tags.PROVISION_POLICIES) != END) {
            if (tag == Tags.PROVISION_POLICY) {
                parsePolicy();
            } else {
                skipTag();
            }
        }
    }

    private void parseDeviceInformation() throws IOException {
        while (nextTag(Tags.SETTINGS_DEVICE_INFORMATION) != END) {
            if (tag == Tags.SETTINGS_STATUS) {
                LogUtils.i(TAG, "DeviceInformation status: %s", getValue());
            } else {
                skipTag();
            }
        }
    }

    @Override
    public boolean parse() throws IOException {
        boolean res = false;
        if (nextTag(START_DOCUMENT) != Tags.PROVISION_PROVISION) {
            throw new IOException();
        }
        while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
            switch (tag) {
                case Tags.PROVISION_STATUS:
                    int status = getValueInt();
                    LogUtils.i(TAG, "Provision status: %d", status);
                    res = (status == 1);
                    break;
                case Tags.SETTINGS_DEVICE_INFORMATION:
                    parseDeviceInformation();
                    break;
                case Tags.PROVISION_POLICIES:
                    parsePolicies();
                    break;
                case Tags.PROVISION_REMOTE_WIPE:
                    // Indicate remote wipe command received
                    mRemoteWipe = true;
                    break;
                default:
                    skipTag();
            }
        }
        return res;
    }

    /**
     * In order to determine whether the device has removable storage, we need to use the
     * StorageVolume class, which is hidden (for now) by the framework.  Without this, we'd have
     * to reject all policies that require sd card encryption.
     *
     * TODO: Rewrite this when an appropriate API is available from the framework
     */
    private boolean hasRemovableStorage() {
        try {
            StorageManager sm = (StorageManager)mContext.getSystemService(Context.STORAGE_SERVICE);
            Class<?> svClass = Class.forName("android.os.storage.StorageVolume");
            Class<?> svManager = Class.forName("android.os.storage.StorageManager");
            Method gvl = svManager.getDeclaredMethod("getVolumeList");
            Object[] volumeList = (Object[]) gvl.invoke(sm);
            for (Object volume: volumeList) {
                Method isRemovable = svClass.getDeclaredMethod("isRemovable");
                Method getDescription = svClass.getDeclaredMethod("getDescription");
                String desc = (String)getDescription.invoke(volume);
                if ((Boolean)isRemovable.invoke(volume)) {
                    log("Removable: " + desc);
                    return true;
                } else {
                    log("Not Removable: " + desc);
                }
            }
            return false;
        } catch (ClassNotFoundException e) {
        } catch (NoSuchMethodException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        }
        // To be safe, we'll always indicate that there IS removable storage
        return true;
    }
}
