1275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdonpackage com.android.exchange.eas;
2ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
3ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.Context;
4ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.net.Uri;
5ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.os.Bundle;
6ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.util.Xml;
7ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
8ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport com.android.emailcommon.provider.Account;
9ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport com.android.emailcommon.provider.HostAuth;
10ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport com.android.emailcommon.service.EmailServiceProxy;
11d793a08771c02d20c81acbedfc44d601d07d1c4fMartin Hibdonimport com.android.emailcommon.service.HostAuthCompat;
12275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdonimport com.android.exchange.CommandStatusException;
13ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport com.android.exchange.Eas;
14ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport com.android.exchange.EasResponse;
15ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport com.android.mail.utils.LogUtils;
16ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
17275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdonimport org.apache.http.HttpEntity;
18ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport org.apache.http.HttpStatus;
1903735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdonimport org.apache.http.client.methods.HttpUriRequest;
20ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport org.apache.http.entity.StringEntity;
21ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport org.xmlpull.v1.XmlPullParser;
22ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport org.xmlpull.v1.XmlPullParserException;
23ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport org.xmlpull.v1.XmlPullParserFactory;
24ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport org.xmlpull.v1.XmlSerializer;
25ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
26ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport java.io.ByteArrayOutputStream;
27ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport java.io.IOException;
28ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
29275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdonpublic class EasAutoDiscover extends EasOperation {
30275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon
3103735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    public final static int ATTEMPT_PRIMARY = 0;
3203735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    public final static int ATTEMPT_ALTERNATE = 1;
3303735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    public final static int ATTEMPT_UNAUTHENTICATED_GET = 2;
3403735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    public final static int ATTEMPT_MAX = 2;
3503735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon
36275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public final static int RESULT_OK = 1;
37275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public final static int RESULT_SC_UNAUTHORIZED = RESULT_OP_SPECIFIC_ERROR_RESULT - 0;
38275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public final static int RESULT_REDIRECT = RESULT_OP_SPECIFIC_ERROR_RESULT - 1;
39275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public final static int RESULT_BAD_RESPONSE = RESULT_OP_SPECIFIC_ERROR_RESULT - 2;
40275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public final static int RESULT_FATAL_SERVER_ERROR = RESULT_OP_SPECIFIC_ERROR_RESULT - 3;
41275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon
42275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    private final static String TAG = LogUtils.TAG;
43ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
44ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String AUTO_DISCOVER_SCHEMA_PREFIX =
45275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            "http://schemas.microsoft.com/exchange/autodiscover/mobilesync/";
46ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String AUTO_DISCOVER_PAGE = "/autodiscover/autodiscover.xml";
47ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
48ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    // Set of string constants for parsing the autodiscover response.
49ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    // TODO: Merge this into Tags.java? It's not quite the same but conceptually belongs there.
50ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_SERVER = "Server";
51ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_TYPE = "Type";
52ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_MOBILE_SYNC = "MobileSync";
53ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_URL = "Url";
54ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_SETTINGS = "Settings";
55ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_ACTION = "Action";
56ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_ERROR = "Error";
57ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_REDIRECT = "Redirect";
58ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_USER = "User";
59ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_EMAIL_ADDRESS = "EMailAddress";
60ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_DISPLAY_NAME = "DisplayName";
61ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_RESPONSE = "Response";
62ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    private static final String ELEMENT_NAME_AUTODISCOVER = "Autodiscover";
63ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
6403735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    private final int mAttemptNumber;
65275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    private final String mUri;
66275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    private final String mUsername;
67275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    private final String mPassword;
68275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    private HostAuth mHostAuth;
69275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    private String mRedirectUri;
70275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon
71ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon
72ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon    private static Account makeAccount(final String username, final String password) {
73ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        final HostAuth hostAuth = new HostAuth();
74ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        hostAuth.mLogin = username;
75ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        hostAuth.mPassword = password;
76ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        hostAuth.mPort = 443;
77ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        hostAuth.mProtocol = Eas.PROTOCOL;
78ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        hostAuth.mFlags = HostAuth.FLAG_SSL | HostAuth.FLAG_AUTHENTICATE;
79ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        final Account account = new Account();
80ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        account.mEmailAddress = username;
81ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        account.mHostAuthRecv = hostAuth;
82ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        return account;
83ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon    }
84ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon
8503735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    public EasAutoDiscover(final Context context, final String uri, final int attemptNumber,
8603735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                           final String username, final String password) {
87275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        // We don't actually need an account or a hostAuth, but the EasServerConnection requires
88275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        // one. Just create dummy values.
89ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        super(context, makeAccount(username, password));
9003735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        mAttemptNumber = attemptNumber;
91275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        mUri = uri;
92275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        mUsername = username;
93275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        mPassword = password;
94ec620ef7363101f5ce8208d17ac496e882d995fdMartin Hibdon        mHostAuth = mAccount.mHostAuthRecv;
95ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
96ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
9703735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    public static String genUri(final String domain, final int attemptNumber) {
9803735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        // Try the following uris in order, as per
9903735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        // http://msdn.microsoft.com/en-us/library/office/jj900169(v=exchg.150).aspx
10003735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        // TODO: That document also describes a fallback strategy to query DNS for an SRV record,
10103735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        // but this would require additional DNS lookup services that are not currently available
10203735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        // in the android platform,
10303735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        switch (attemptNumber) {
10403735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon            case ATTEMPT_PRIMARY:
10503735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                return "https://" + domain + AUTO_DISCOVER_PAGE;
10603735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon            case ATTEMPT_ALTERNATE:
10703735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                return "https://autodiscover." + domain + AUTO_DISCOVER_PAGE;
10803735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon            case ATTEMPT_UNAUTHENTICATED_GET:
10903735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                return "http://autodiscover." + domain + AUTO_DISCOVER_PAGE;
11003735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon            default:
11103735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                LogUtils.wtf(TAG, "Illegal attempt number %d", attemptNumber);
11203735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                return null;
11303735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        }
11403735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    }
11503735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon
116275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    protected String getRequestUri() {
117275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        return mUri;
118275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    }
119ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
120275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public static String getDomain(final String login) {
121275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        final int amp = login.indexOf('@');
122275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        if (amp < 0) {
123ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            return null;
124ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
125275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        return login.substring(amp + 1);
126275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    }
127432f1de519032c9381650ba5a40d0ff06d19c51bYu Ping Hu
128275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    @Override
129275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    protected String getCommand() {
130275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        return null;
131275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    }
132275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon
133275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    @Override
134275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    protected HttpEntity getRequestEntity() throws IOException, MessageInvalidException {
135ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        try {
136ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final XmlSerializer s = Xml.newSerializer();
137ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
138ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.setOutput(os, "UTF-8");
139ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.startDocument("UTF-8", false);
140ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.startTag(null, "Autodiscover");
141ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.attribute(null, "xmlns", AUTO_DISCOVER_SCHEMA_PREFIX + "requestschema/2006");
142ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.startTag(null, "Request");
143275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            s.startTag(null, "EMailAddress").text(mUsername).endTag(null, "EMailAddress");
144ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.startTag(null, "AcceptableResponseSchema");
145ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.text(AUTO_DISCOVER_SCHEMA_PREFIX + "responseschema/2006");
146ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.endTag(null, "AcceptableResponseSchema");
147ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.endTag(null, "Request");
148ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.endTag(null, "Autodiscover");
149ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            s.endDocument();
150ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            return new StringEntity(os.toString());
151ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        } catch (final IOException e) {
152ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            // For all exception types, we can simply punt on autodiscover.
153ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        } catch (final IllegalArgumentException e) {
154ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        } catch (final IllegalStateException e) {
155ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
156ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        return null;
157ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
158ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
15903735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    /**
16003735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon     * Create the request object for this operation.
16103735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon     * The default is to use a POST, but some use other request types (e.g. Options).
16203735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon     * @return An {@link org.apache.http.client.methods.HttpUriRequest}.
16303735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon     * @throws IOException
16403735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon     */
16503735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    protected HttpUriRequest makeRequest() throws IOException, MessageInvalidException {
16603735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        final String requestUri = getRequestUri();
16703735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        HttpUriRequest req;
16803735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        if (mAttemptNumber == ATTEMPT_UNAUTHENTICATED_GET) {
16903735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon            req = mConnection.makeGet(requestUri);
17003735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        } else {
17103735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon            req = mConnection.makePost(requestUri, getRequestEntity(),
17203735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon                    getRequestContentType(), addPolicyKeyHeaderToRequest());
17303735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        }
17403735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon        return req;
17503735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon    }
17603735a839ba61710f887fffd6d3f605c0b127c2eMartin Hibdon
177275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public String getRedirectUri() {
178275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        return mRedirectUri;
179ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
180ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
181275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    @Override
182275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    protected int handleResponse(final EasResponse response) throws
183275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            IOException, CommandStatusException {
184275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        // resp is either an authentication error, or a good response.
185275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        final int code = response.getStatus();
186ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
187275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        if (response.isRedirectError()) {
188275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            final String loc = response.getRedirectAddress();
189ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (loc != null && loc.startsWith("http")) {
190ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                LogUtils.d(TAG, "Posting autodiscover to redirect: " + loc);
191275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                mRedirectUri = loc;
192275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                return RESULT_REDIRECT;
193275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            } else {
194275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                LogUtils.w(TAG, "Invalid redirect %s", loc);
195275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                return RESULT_FATAL_SERVER_ERROR;
196ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
197ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
198ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
199ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        if (code == HttpStatus.SC_UNAUTHORIZED) {
200275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            LogUtils.w(TAG, "Autodiscover received SC_UNAUTHORIZED");
201275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            return RESULT_SC_UNAUTHORIZED;
202ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        } else if (code != HttpStatus.SC_OK) {
203ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            // We'll try the next address if this doesn't work
204ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            LogUtils.d(TAG, "Bad response code when posting autodiscover: %d", code);
205275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            return RESULT_BAD_RESPONSE;
206275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        } else {
207275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            mHostAuth = parseAutodiscover(response);
208275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            if (mHostAuth != null) {
209275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                // Fill in the rest of the HostAuth
210275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                // We use the user name and password that were successful during
211275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                // the autodiscover process
212275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                mHostAuth.mLogin = mUsername;
213275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                mHostAuth.mPassword = mPassword;
214275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                // Note: there is no way we can auto-discover the proper client
215275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                // SSL certificate to use, if one is needed.
2163860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                if (mHostAuth.mPort == -1) {
2173860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                    mHostAuth.mPort = 443;
2183860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                }
219275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                mHostAuth.mProtocol = Eas.PROTOCOL;
220275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                mHostAuth.mFlags = HostAuth.FLAG_SSL | HostAuth.FLAG_AUTHENTICATE;
221275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                return RESULT_OK;
222275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            } else {
223275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                return RESULT_HARD_DATA_FAILURE;
224275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon            }
225ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
226275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    }
227ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
228275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon    public Bundle getResultBundle() {
229275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        final Bundle bundle = new Bundle(2);
230d793a08771c02d20c81acbedfc44d601d07d1c4fMartin Hibdon        final HostAuthCompat hostAuthCompat = new HostAuthCompat(mHostAuth);
231275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        bundle.putParcelable(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_HOST_AUTH,
232d793a08771c02d20c81acbedfc44d601d07d1c4fMartin Hibdon                hostAuthCompat);
233275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        bundle.putInt(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_ERROR_CODE,
234275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon                RESULT_OK);
235275e73703e09a1211ae6aa6fc2a43226e1fcdeedMartin Hibdon        return bundle;
236ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
237ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
238ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    /**
239ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * Parse the Server element of the server response.
240ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param parser The {@link XmlPullParser}.
241ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param hostAuth The {@link HostAuth} to populate with the results of parsing.
242ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws XmlPullParserException
243ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws IOException
244ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     */
24556d35257ef1493e849522c3c2828d904e4c5531fScott Kennedy    private static void parseServer(final XmlPullParser parser, final HostAuth hostAuth)
246ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            throws XmlPullParserException, IOException {
247ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        boolean mobileSync = false;
248ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        while (true) {
249ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final int type = parser.next();
250ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (type == XmlPullParser.END_TAG && parser.getName().equals(ELEMENT_NAME_SERVER)) {
251ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                break;
252ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            } else if (type == XmlPullParser.START_TAG) {
253ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                final String name = parser.getName();
254ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                if (name.equals(ELEMENT_NAME_TYPE)) {
255ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    if (parser.nextText().equals(ELEMENT_NAME_MOBILE_SYNC)) {
256ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                        mobileSync = true;
257ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    }
258ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                } else if (mobileSync && name.equals(ELEMENT_NAME_URL)) {
259ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    final String url = parser.nextText();
260ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    if (url != null) {
261ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                        LogUtils.d(TAG, "Autodiscover URL: %s", url);
2623860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                        final Uri uri = Uri.parse(url);
2633860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                        hostAuth.mAddress = uri.getHost();
2643860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                        int port = uri.getPort();
2653860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                        if (port != -1) {
2663860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                            hostAuth.mPort = port;
2673860b0c076536883b808c5d865e7e3a509527a69Jorge Ruesga                        }
268ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    }
269ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                }
270ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
271ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
272ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
273ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
274ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    /**
275ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * Parse the Settings element of the server response.
276ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param parser The {@link XmlPullParser}.
277ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param hostAuth The {@link HostAuth} to populate with the results of parsing.
278ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws XmlPullParserException
279ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws IOException
280ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     */
28156d35257ef1493e849522c3c2828d904e4c5531fScott Kennedy    private static void parseSettings(final XmlPullParser parser, final HostAuth hostAuth)
282ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            throws XmlPullParserException, IOException {
283ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        while (true) {
284ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final int type = parser.next();
285ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (type == XmlPullParser.END_TAG && parser.getName().equals(ELEMENT_NAME_SETTINGS)) {
286ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                break;
287ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            } else if (type == XmlPullParser.START_TAG) {
288ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                final String name = parser.getName();
289ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                if (name.equals(ELEMENT_NAME_SERVER)) {
290ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    parseServer(parser, hostAuth);
291ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                }
292ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
293ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
294ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
295ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
296ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    /**
297ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * Parse the Action element of the server response.
298ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param parser The {@link XmlPullParser}.
299ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param hostAuth The {@link HostAuth} to populate with the results of parsing.
300ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws XmlPullParserException
301ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws IOException
302ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     */
30356d35257ef1493e849522c3c2828d904e4c5531fScott Kennedy    private static void parseAction(final XmlPullParser parser, final HostAuth hostAuth)
304ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            throws XmlPullParserException, IOException {
305ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        while (true) {
306ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final int type = parser.next();
307ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (type == XmlPullParser.END_TAG && parser.getName().equals(ELEMENT_NAME_ACTION)) {
308ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                break;
309ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            } else if (type == XmlPullParser.START_TAG) {
310ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                final String name = parser.getName();
311ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                if (name.equals(ELEMENT_NAME_ERROR)) {
312ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    // Should parse the error
313ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                } else if (name.equals(ELEMENT_NAME_REDIRECT)) {
314ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    LogUtils.d(TAG, "Redirect: " + parser.nextText());
315ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                } else if (name.equals(ELEMENT_NAME_SETTINGS)) {
316ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    parseSettings(parser, hostAuth);
317ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                }
318ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
319ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
320ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
321ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
322ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    /**
323ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * Parse the User element of the server response.
324ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param parser The {@link XmlPullParser}.
325ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param hostAuth The {@link HostAuth} to populate with the results of parsing.
326ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws XmlPullParserException
327ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws IOException
328ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     */
32956d35257ef1493e849522c3c2828d904e4c5531fScott Kennedy    private static void parseUser(final XmlPullParser parser, final HostAuth hostAuth)
330ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            throws XmlPullParserException, IOException {
331ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        while (true) {
332ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            int type = parser.next();
333ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (type == XmlPullParser.END_TAG && parser.getName().equals(ELEMENT_NAME_USER)) {
334ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                break;
335ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            } else if (type == XmlPullParser.START_TAG) {
336ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                String name = parser.getName();
337ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                if (name.equals(ELEMENT_NAME_EMAIL_ADDRESS)) {
338ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    final String addr = parser.nextText();
339ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    LogUtils.d(TAG, "Autodiscover, email: %s", addr);
340ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                } else if (name.equals(ELEMENT_NAME_DISPLAY_NAME)) {
341ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    final String dn = parser.nextText();
342ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    LogUtils.d(TAG, "Autodiscover, user: %s", dn);
343ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                }
344ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
345ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
346ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
347ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
348ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    /**
349ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * Parse the Response element of the server response.
350ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param parser The {@link XmlPullParser}.
351ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param hostAuth The {@link HostAuth} to populate with the results of parsing.
352ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws XmlPullParserException
353ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @throws IOException
354ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     */
35556d35257ef1493e849522c3c2828d904e4c5531fScott Kennedy    private static void parseResponse(final XmlPullParser parser, final HostAuth hostAuth)
356ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            throws XmlPullParserException, IOException {
357ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        while (true) {
358ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final int type = parser.next();
359ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (type == XmlPullParser.END_TAG && parser.getName().equals(ELEMENT_NAME_RESPONSE)) {
360ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                break;
361ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            } else if (type == XmlPullParser.START_TAG) {
362ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                final String name = parser.getName();
363ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                if (name.equals(ELEMENT_NAME_USER)) {
364ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    parseUser(parser, hostAuth);
365ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                } else if (name.equals(ELEMENT_NAME_ACTION)) {
366ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    parseAction(parser, hostAuth);
367ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                }
368ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
369ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
370ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
371ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
372ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    /**
373ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * Parse the server response for the final {@link HostAuth}.
374ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @param resp The {@link EasResponse} from the server.
375ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     * @return The final {@link HostAuth} for this server.
376ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu     */
37756d35257ef1493e849522c3c2828d904e4c5531fScott Kennedy    private static HostAuth parseAutodiscover(final EasResponse resp) {
378ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        // The response to Autodiscover is regular XML (not WBXML)
379ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        try {
380ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
381ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            parser.setInput(resp.getInputStream(), "UTF-8");
382ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (parser.getEventType() != XmlPullParser.START_DOCUMENT) {
383ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                return null;
384ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
385ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (parser.next() != XmlPullParser.START_TAG) {
386ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                return null;
387ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
388ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            if (!parser.getName().equals(ELEMENT_NAME_AUTODISCOVER)) {
389ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                return null;
390ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
391ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu
392ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            final HostAuth hostAuth = new HostAuth();
393ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            while (true) {
394ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                final int type = parser.nextTag();
395ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                if (type == XmlPullParser.END_TAG && parser.getName()
396ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                        .equals(ELEMENT_NAME_AUTODISCOVER)) {
397ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    break;
398ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                } else if (type == XmlPullParser.START_TAG && parser.getName()
399ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                        .equals(ELEMENT_NAME_RESPONSE)) {
400ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    parseResponse(parser, hostAuth);
401ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    // Valid responses will set the address.
402ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    if (hostAuth.mAddress != null) {
403ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                        return hostAuth;
404ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                    }
405ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu                }
406ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            }
407ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        } catch (final XmlPullParserException e) {
408ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            // Parse error.
409ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        } catch (final IOException e) {
410ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu            // Error reading parser.
411ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        }
412ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu        return null;
413ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu    }
414ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu}
415