Java tutorial
/* * Copyright (C) 2013 Sasha Vasko <sasha at aftercode dot net> * * 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.wifiafterconnect; import java.net.HttpURLConnection; import java.net.Inet4Address; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONException; import org.json.JSONObject; import android.util.Log; import com.wifiafterconnect.handlers.CaptivePageHandler; import com.wifiafterconnect.html.HtmlForm; import com.wifiafterconnect.html.HtmlPage; import com.wifiafterconnect.html.WISPAccessGatewayParam; import com.wifiafterconnect.http.HttpConnectionWrapper; import com.wifiafterconnect.http.HttpConnectionFactory; import com.wifiafterconnect.util.HttpInput; import com.wifiafterconnect.util.Preferences; import com.wifiafterconnect.util.Worker; public class ParsedHttpInput extends Worker { public class JsonInput extends HttpInput { private JSONObject json = null; public JsonInput(URL url) { super(url); // TODO Auto-generated constructor stub } @Override public boolean parse(String source) { json = null; if (!super.parse(source)) return false; try { json = new JSONObject(source); } catch (JSONException e) { } return (json != null); } public JSONObject getJSONObject() { return json; } public JSONObject getJSONObject(final String name) throws JSONException { return json != null ? json.getJSONObject(name) : null; } } private CaptivePageHandler captiveHandler = null; private HttpInput httpInput = null; private Map<String, String> httpHeaders; public static final String HTTP_HEADER_LOCATION = "Location"; public ParsedHttpInput(Worker other, URL url, String html, Map<String, String> headers) { super(other); // create a copy of headers hash map, so that we retain original input in case // parameter gets modified later on by the caller for some reason. httpHeaders = new HashMap<String, String>(headers); parse(url, html); } private void parse(URL url, String input) { captiveHandler = null; httpInput = null; if (input.startsWith("{")) { // TODO implement parsing as JSON??? JsonInput jsonInput = new JsonInput(url); if (!jsonInput.parse(input)) error("Failed to parse JSON input"); else { httpInput = jsonInput; captiveHandler = CaptivePageHandler.autodetect(httpInput); } } else { HtmlPage htmlPage = new HtmlPage(url); if (!htmlPage.parse(input)) { error("Failed to parse the HTML page"); } else { httpInput = htmlPage; debug("HTML page parsed. OnLoad = [" + htmlPage.getOnLoad() + "]"); if (!submitOnLoad(htmlPage)) { // Probably the actual login page captiveHandler = CaptivePageHandler.autodetect(httpInput); } } } if (captiveHandler != null) debug("Detected page handler " + captiveHandler); // Fallback - plain text container if (httpInput == null) { httpInput = new HttpInput(url); httpInput.parse(input); } } public HtmlPage getHtmlPage() { return (httpInput != null && httpInput instanceof HtmlPage) ? (HtmlPage) httpInput : null; } public JSONObject getJSONObject() { return (httpInput != null && httpInput instanceof JsonInput) ? ((JsonInput) httpInput).getJSONObject() : null; } public JSONObject getJSONObject(final String name) throws JSONException { return (httpInput != null && httpInput instanceof JsonInput) ? ((JsonInput) httpInput).getJSONObject(name) : null; } /* * Guaranteed not to return null */ public String getHttpHeader(final String key) { String val = httpHeaders.get(key); return val == null ? "" : val; } public HtmlForm getHtmlForm() { HtmlPage hp = getHtmlPage(); return hp != null ? hp.getForm() : null; } public String buildPostData(final WifiAuthParams authParams) { if (captiveHandler != null) return captiveHandler.getPostData(authParams); HtmlForm form = getHtmlForm(); if (form != null) return form.formatPostData(); return ""; } public boolean checkParamsMissing(WifiAuthParams params) { Log.d(Constants.TAG, "checkParamsMissing: CaptiveHandler = " + captiveHandler); if (captiveHandler != null) return captiveHandler.checkParamsMissing(params); return false; } public WifiAuthParams addMissingParams(WifiAuthParams params) { Log.d(Constants.TAG, "addMissingParams: CaptiveHandler = " + captiveHandler); if (captiveHandler != null) return captiveHandler.addMissingParams(params); return null; } public ParsedHttpInput handleAutoRedirects(int maxRequests, boolean authFollowup) { debug("handleAutoRedirects(): this = " + this + " max Requests = " + maxRequests + " authFollowup = " + authFollowup); if (maxRequests <= 0 || (Preferences.getWISPrEnabled() && getWISPr() != null)) // per WISPr 2.0 spec 7.3.3 return this; ParsedHttpInput result = null; String redirectLoc = getHttpHeader(HTTP_HEADER_LOCATION); if (BuildConfig.DEBUG) debug("submitOnLoad() = " + submitOnLoad() + ", hasSubmittableForm = " + hasSubmittableForm() + ", redirectLoc = " + redirectLoc + ", hasMetaRefresh() = " + hasMetaRefresh()); if (submitOnLoad() || (authFollowup && hasSubmittableForm())) { debug("Handling onLoad submit ..."); result = postForm(null); } else if (!redirectLoc.isEmpty()) { debug("Handling Location redirect ..."); result = getRefresh(redirectLoc); } else if (hasMetaRefresh() && (authFollowup || getHtmlForm() == null)) { debug("Handling meta refresh ..."); result = getRefresh(null); } else { debug("No redirect action detected ..."); return this; } if (result != null) result = result.handleAutoRedirects(maxRequests - 1, authFollowup); debug("handleAutoRedirects(): result = " + result); return result; } public ParsedHttpInput authenticateCaptivePortal(WifiAuthParams authParams) { return (captiveHandler != null) ? captiveHandler.authenticate(this, authParams) : null; } public CaptivePageHandler.States getCaptivePortalState() { return (captiveHandler != null) ? captiveHandler.getState() : CaptivePageHandler.States.Failed; } public boolean submitOnLoad(HtmlPage hp) { if (hp != null) { String onLoad = hp.getOnLoad(); return onLoad.equalsIgnoreCase("document.forms[0].submit();") || onLoad.equalsIgnoreCase("document.form.submit();") || onLoad.endsWith(".submit();"); // this one is probably enough } return false; } public boolean submitOnLoad() { return submitOnLoad(getHtmlPage()); } public final String getHtml() { return (httpInput != null && httpInput instanceof HtmlPage) ? httpInput.getSource() : ""; } public final String getRaw() { return (httpInput != null) ? httpInput.getSource() : ""; } public final URL getURL() { return (httpInput != null) ? httpInput.getURL() : null; } public boolean hasMetaRefresh() { HtmlPage hp = getHtmlPage(); return hp != null && hp.hasMetaRefresh(); } public HtmlPage.MetaRefresh getMetaRefresh() { HtmlPage hp = getHtmlPage(); return hp != null ? hp.getMetaRefresh() : null; } public boolean isKnownCaptivePortal() { return (captiveHandler != null); } /* ###################################################### * The Captive Portal check code from android. Unlike them, * we actually need the portal page, so that we can post a response. * * Copyright (C) 2012 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); */ public static InetAddress lookupHost(String hostname) { InetAddress inetAddress[]; try { inetAddress = InetAddress.getAllByName(hostname); } catch (UnknownHostException e) { return null; } for (InetAddress a : inetAddress) { if (a instanceof Inet4Address) return a; } return null; } /* ====================================================== * End of the The Captive Portal check code from android */ public URL getFormPostURL() { return (captiveHandler != null) ? captiveHandler.getPostURL() : getURL(); } public WISPAccessGatewayParam getWISPr() { HtmlPage hp = getHtmlPage(); return (hp != null) ? hp.getWISPr() : null; } public String getCookies() { // TODO Auto-generated method stub return null; } public boolean hasSubmittableForm() { HtmlPage hp = getHtmlPage(); return hp != null && hp.hasSubmittableForm(); } public boolean hasForm() { HtmlPage hp = getHtmlPage(); return (hp != null && hp.getForm() != null); } public String getURLQueryVar(String varName) { return httpInput.getURLQueryVar(varName); } public ParsedHttpInput postForm(WifiAuthParams authParams) { URL url = getFormPostURL(); String postDataString = buildPostData(authParams); String cookies = getCookies(); return post(this, url, postDataString, cookies, getURL().toString()); } public URL makeRefreshURL(String urlString) { URL url = null; if (httpInput != null) { try { HtmlPage.MetaRefresh metaRefresh; if (urlString != null) url = httpInput.makeURL(urlString); else if ((metaRefresh = getMetaRefresh()) != null) { url = metaRefresh.getURL(); if (url != null && metaRefresh.getTimeout() > 0) { try { Thread.sleep(1000 * Math.min(metaRefresh.getTimeout(), Constants.MAX_REFRESH_TIMEOUT)); } catch (InterruptedException e) { } // don't care } } } catch (MalformedURLException ee) { exception(ee); } } return url; } public ParsedHttpInput getRefresh(String urlString) { URL url = makeRefreshURL(urlString); return url == null ? null : get(this, url, getURL().toString()); } public static void showRequestProperties(Worker context, HttpURLConnection conn) { Map<String, List<String>> reqProps = conn.getRequestProperties(); context.debug("RequestProperties for [" + conn.getURL() + "]"); for (String key : reqProps.keySet()) { String propStr = "RequestPropery[" + key + "] = {"; for (String val : reqProps.get(key)) { propStr += "[" + val + "]"; } context.debug(propStr + "}"); } } public static ParsedHttpInput post(Worker context, URL url, String postDataString, String cookies, String referer) { HttpConnectionWrapper conn = HttpConnectionFactory.INSTANCE.getConnection(); conn.setUrl(url); return conn.post(context, postDataString, cookies, referer) ? valueOf(context, conn) : null; } private static ParsedHttpInput valueOf(Worker context, HttpConnectionWrapper conn) { ParsedHttpInput parsed = null; if (conn != null) { parsed = new ParsedHttpInput(context, conn.getUrl(), conn.getData(), conn.getHeaders()); } return parsed; } public static ParsedHttpInput get(Worker context, URL url, String referer) { HttpConnectionWrapper conn = HttpConnectionFactory.INSTANCE.getConnection(); conn.setUrl(url); return conn.get(context, referer) ? valueOf(context, conn) : null; } }