Java tutorial
/* * Copyright (C) 2010 Koni * * This file is only usefull as part of WebSMS. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; If not, see <http://www.gnu.org/licenses/>. */ package com.rothconsulting.android.websms.connector.schoolnet; import java.net.HttpURLConnection; import java.util.ArrayList; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import com.google.analytics.tracking.android.GoogleAnalytics; import com.google.analytics.tracking.android.Tracker; import de.ub0r.android.websms.connector.common.Connector; import de.ub0r.android.websms.connector.common.ConnectorCommand; import de.ub0r.android.websms.connector.common.ConnectorSpec; import de.ub0r.android.websms.connector.common.ConnectorSpec.SubConnectorSpec; import de.ub0r.android.websms.connector.common.Log; import de.ub0r.android.websms.connector.common.Utils; import de.ub0r.android.websms.connector.common.Utils.HttpOptions; import de.ub0r.android.websms.connector.common.WebSMSException; /** * AsyncTask to manage IO to Schoolnet API. * * @author koni */ public class ConnectorSchoolnet extends Connector { /** Tag for output. */ private static final String TAG = "Schoolnet"; /** Dummy String */ private static final String DUMMY = "???"; /** Homepage URL. */ private static final String URL_LOGIN_PAGE = "http://www.schoolnet.ch/DE/HomeDE.htm"; /** Login URL. */ private static final String URL_LOGIN_ACTION = "http://www.schoolnet.ch/schoolnet/Templates/HomePage.aspx?NRMODE=Published&NRNODEGUID=%7bFC1600E3-5CFE-4E47-A279-A0917FF86261%7d&NRORIGINALURL=%2fDE%2fHomeDE%2ehtm&NRCACHEHINT=NoModifyGuest"; /** SMS send action URL. */ private static final String URL_SEND_PAGE = "http://www.schoolnet.ch/DE/FreundeInternet/SMS/"; /** SMS send action URL. */ private static final String URL_SEND_ACTION = "http://www.schoolnet.ch/schoolnet/Templates/Template5Slots.aspx?NRMODE=Published&NRNODEGUID=%7bE1B58CDA-3DA6-45D3-9F95-F8E078143033%7d&NRORIGINALURL=%2fDE%2fFreundeInternet%2fSMS%2f&NRCACHEHINT=NoModifyLoggedIn"; /** SMS Credit */ private String SMS_CREDIT = DUMMY; /** HTTP User agent. */ private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:31.0) Gecko/20100101 Firefox/31.0"; /** SMS Encoding */ private static final String ENCODING = "UTF-8"; /** Check whether this connector is bootstrapping. */ private static boolean inBootstrap = false; /** Only when mobile number is entered, check for sender errors. */ private static boolean checkForSenderErrors = false; /** My Ad-ID */ private static final String AD_UNITID = "ca-app-pub-5619114666968507/9953800139"; /** My Analytics-ID */ private static final String ANALYTICS_ID = "UA-38114228-3"; private Tracker mGaTracker; private GoogleAnalytics mGaInstance; /** */ private String VIEWSTATE_LOGIN = "VIEWSTATE_LOGIN"; /** */ private String VIEWSTATE_SEND = "VIEWSTATE_SEND"; private void initAnalytics(final Context context) { // Get singleton. this.mGaInstance = GoogleAnalytics.getInstance(context); // To set the default tracker, use: // First get a tracker using a new property ID. Tracker newTracker = this.mGaInstance.getTracker(ANALYTICS_ID); // Then make newTracker the default tracker globally. this.mGaInstance.setDefaultTracker(newTracker); // Get default tracker. this.mGaTracker = this.mGaInstance.getDefaultTracker(); } /** * {@inheritDoc} */ @Override public final ConnectorSpec initSpec(final Context context) { final String name = context.getString(R.string.connector_schoolnet_name); ConnectorSpec c = new ConnectorSpec(name); c.setAuthor(context.getString(R.string.connector_schoolnet_author)); c.setBalance(null); c.setAdUnitId(AD_UNITID); c.setCapabilities(ConnectorSpec.CAPABILITIES_BOOTSTRAP | ConnectorSpec.CAPABILITIES_UPDATE | ConnectorSpec.CAPABILITIES_SEND | ConnectorSpec.CAPABILITIES_PREFS); c.addSubConnector("schoolnet", c.getName(), SubConnectorSpec.FEATURE_MULTIRECIPIENTS); return c; } /** * {@inheritDoc} */ @Override public final ConnectorSpec updateSpec(final Context context, final ConnectorSpec connectorSpec) { this.log("Start updateSpec"); final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(context); if (p.getBoolean(Preferences.PREFS_ENABLED, false)) { if (p.getString(Preferences.PREFS_USER, "").length() > 0 && p.getString(Preferences.PREFS_PASSWORD, "") // . .length() > 0) { connectorSpec.setReady(); } else { connectorSpec.setStatus(ConnectorSpec.STATUS_ENABLED); } } else { connectorSpec.setStatus(ConnectorSpec.STATUS_INACTIVE); } this.log("End updateSpec"); return connectorSpec; } /** * {@inheritDoc} */ @Override protected final void doBootstrap(final Context context, final Intent intent) throws WebSMSException { this.log("Start doBootstrap"); checkForSenderErrors = false; if (inBootstrap && !this.SMS_CREDIT.equals(DUMMY)) { this.log("already in bootstrap: skip bootstrap"); return; } // get schoolnet view state this.sendData(URL_LOGIN_PAGE, context, null, false); inBootstrap = true; final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(context); ArrayList<BasicNameValuePair> postParameter = new ArrayList<BasicNameValuePair>(); postParameter.add(new BasicNameValuePair("BotM:ucUser:ucUser2Col:txtUsername", p.getString(Preferences.PREFS_USER, ""))); postParameter.add(new BasicNameValuePair("BotM:ucUser:ucUser2Col:txtPassword", p.getString(Preferences.PREFS_PASSWORD, ""))); postParameter.add(new BasicNameValuePair("__EVENTTARGET", "BotM:ucUser:ucUser2Col:cmdLogin")); postParameter.add(new BasicNameValuePair("__EVENTARGUMENT", "")); postParameter.add(new BasicNameValuePair("__VIEWSTATE", this.VIEWSTATE_LOGIN)); ArrayList<Header> headers = new ArrayList<Header>(); headers.add(new BasicHeader("Referer", URL_LOGIN_PAGE)); this.sendData(URL_LOGIN_ACTION, context, postParameter, true); this.log("End doBootstrap"); } /** * {@inheritDoc} */ @Override protected final void doUpdate(final Context context, final Intent intent) throws WebSMSException { this.log("Start doUpdate"); this.doBootstrap(context, intent); this.initAnalytics(context); // ArrayList<Header> headers = new ArrayList<Header>(); // headers.add(new BasicHeader("Referer", URL_LOGIN_PAGE)); this.sendData(URL_SEND_PAGE, context, null, true); this.getSpec(context).setBalance(this.SMS_CREDIT); // Google analytics if (this.mGaTracker != null) { this.log("Tracking ID=" + this.mGaTracker.getTrackingId()); this.mGaTracker.sendEvent(TAG, "doUpdate", "Balance: " + this.getSpec(context).getBalance(), 0L); } this.log("End doUpdate"); } /** * {@inheritDoc} */ @Override protected final void doSend(final Context context, final Intent intent) throws WebSMSException { this.log("Start doSend"); this.doBootstrap(context, intent); ConnectorCommand command = new ConnectorCommand(intent); // SMS Text String text = command.getText(); this.log("text.length()=" + text.length()); this.log("text=" + text); // SMS Recipients String[] to = command.getRecipients(); String prefix = ""; String number = ""; if (to == null || to.length > 10) { String error = context.getString(R.string.connector_schoolnet_max_10_recipients); this.log("----- throwing WebSMSException: " + error); throw new WebSMSException(error); } // get schoolnet view state this.sendData(URL_SEND_PAGE, context, null, false); for (int i = 0; i < to.length; i++) { if (to[i] != null && to[i].length() > 1) { // Building POST parameter ArrayList<BasicNameValuePair> postParameter = new ArrayList<BasicNameValuePair>(); postParameter.add(new BasicNameValuePair("__EVENTTARGET", "Layout1:PresentationModeControlsContainer:_ctl2:_ctl0:_ctl0:cmdAnswer")); postParameter.add(new BasicNameValuePair("__EVENTARGUMENT", "")); postParameter.add(new BasicNameValuePair("__VIEWSTATE", this.VIEWSTATE_SEND)); postParameter.add(new BasicNameValuePair( "Layout1:PresentationModeControlsContainer:_ctl2:_ctl0:_ctl0:txt_PhonePrefix", "")); postParameter.add(new BasicNameValuePair( "Layout1:PresentationModeControlsContainer:_ctl2:_ctl0:_ctl0:txt_Phone", "rbSendNumber")); postParameter.add(new BasicNameValuePair( "Layout1:PresentationModeControlsContainer:_ctl2:_ctl0:_ctl0:txt_Message", text)); String fullNumber = Utils.getRecipientsNumber(to[i]); this.log("--- anzahl=" + to.length); this.log("--- to[" + i + "]=" + to[i]); this.log("--- fullNumber=" + fullNumber); if (fullNumber.startsWith("+417")) { prefix = fullNumber.substring(0, 5); number = fullNumber.substring(5, 12); this.log("--- prefix=" + prefix); this.log("--- number=" + number); } if (fullNumber.startsWith("00417")) { prefix = fullNumber.substring(0, 6); number = fullNumber.substring(6, 13); this.log("--- prefix=" + prefix); this.log("--- number=" + number); } if (fullNumber.startsWith("07")) { prefix = fullNumber.substring(0, 3); number = fullNumber.substring(3, 10); this.log("--- prefix=" + prefix); this.log("--- number=" + number); } postParameter.add(new BasicNameValuePair( "Layout1:PresentationModeControlsContainer:_ctl2:_ctl0:_ctl0:txtSmsListPrefix", prefix)); postParameter.add(new BasicNameValuePair( "Layout1:PresentationModeControlsContainer:_ctl2:_ctl0:_ctl0:txtSmsListHandy", number)); ArrayList<Header> headers = new ArrayList<Header>(); headers.add(new BasicHeader("Referer", URL_SEND_PAGE)); // Google analytics if (this.mGaTracker == null) { this.initAnalytics(context); } if (this.mGaTracker != null) { this.log("Tracking ID=" + this.mGaTracker.getTrackingId()); this.mGaTracker.sendEvent(TAG, "Send SMS", "Count receiver: " + i + 1, 0L); } // push data this.sendData(URL_SEND_ACTION, context, postParameter, true); this.log("End doSend: " + i); } } } /** * Sending the request (Login or SMS) * * @param url * @param context * @param postParameter * @param parseHtml * @throws WebSMSException */ private void sendData(final String url, final Context context, final ArrayList<BasicNameValuePair> postParameter, final boolean parseHtml) throws WebSMSException { this.log("Start sendData"); try { this.log("URL: " + url); // send data HttpOptions httpOptions = new HttpOptions(); httpOptions.url = url; httpOptions.userAgent = USER_AGENT; // httpOptions.trustAll = true; if (postParameter != null) { this.log("UrlEncodedFormEntity(postParameter,ENCODING)"); httpOptions.postData = new UrlEncodedFormEntity(postParameter, ENCODING); } this.log("send data: getHttpClient(...)"); HttpResponse response = Utils.getHttpClient(httpOptions); int respStatus = response.getStatusLine().getStatusCode(); this.log("response status =" + respStatus); this.log("response statusLine=" + response.getStatusLine()); if (respStatus != HttpURLConnection.HTTP_OK) { this.log("response headers =\n" + ConnectorSchoolnet.getHeaders(response.getAllHeaders())); throw new WebSMSException(context, R.string.error_http, "" + respStatus); } String htmlText = Utils.stream2str(response.getEntity().getContent()).trim(); if (htmlText == null || htmlText.length() == 0) { throw new WebSMSException(context, R.string.error_service); } this.log("----- Start HTTP RESPONSE--"); this.log(htmlText); this.log("----- End HTTP RESPONSE--"); this.getSchoolnetViewstate(htmlText, url); if (parseHtml) { // this.getPhoneNumber(htmlText, context); String guthabenGratis = this.getGuthabenGratis(htmlText, context); String errorMessage = this.getErrorBlockMessage(htmlText, context); if (guthabenGratis != null && !guthabenGratis.equals("")) { this.SMS_CREDIT = "SMS=" + guthabenGratis; } if (errorMessage != null && !errorMessage.equals("")) { this.log("----- throwing WebSMSException: " + errorMessage); throw new WebSMSException(errorMessage); } this.getSpec(context).setBalance(this.SMS_CREDIT); } htmlText = null; } catch (Exception e) { Log.e(TAG, null, e); throw new WebSMSException(e.getMessage()); } } private String getGuthabenGratis(final String htmlText, final Context context) { String guthabenGratis = ""; int indexStartSMSCredit = htmlText.indexOf("userSnPoints"); if (indexStartSMSCredit > 0) { guthabenGratis = htmlText.substring(indexStartSMSCredit + 17, indexStartSMSCredit + 21); guthabenGratis = guthabenGratis.replace("<", ""); guthabenGratis = guthabenGratis.replace("/", ""); guthabenGratis = guthabenGratis.replace("b", ""); } this.log("indexOf Gratis=" + indexStartSMSCredit + " -- Gratis=" + guthabenGratis); return guthabenGratis.trim(); } private String getErrorBlockMessage(final String htmlText, final Context context) { String message = ""; if (checkForSenderErrors) { int indexStartErrorBlock = htmlText.indexOf("errorBlock"); int indexEndeErrorBlock = htmlText.indexOf("Die SMS/MMS wurde nicht versandt"); if (indexStartErrorBlock > 0 && indexEndeErrorBlock > 0) { message = htmlText.substring(indexStartErrorBlock + 28, indexEndeErrorBlock); } this.log("indexStartOf errorBlock =" + indexStartErrorBlock + ", indexEndeOf errorBlock =" + indexEndeErrorBlock + " -- Message=" + message); if (message.trim().startsWith("Die Absendernummer hat sich gendert")) { message = context.getString(R.string.connector_schoolnet_wrong_mobilenumber); } else { message = ""; } } return message.trim(); } private void getSchoolnetViewstate(final String htmlText, final String url) { int tokenLength = 40000; if (url.equals(URL_LOGIN_PAGE) || url.equals(URL_SEND_PAGE)) { String viewstateTmp = ""; int indexStart = htmlText.indexOf("__VIEWSTATE\" value=\""); if (htmlText.length() < tokenLength) { tokenLength = htmlText.length() - indexStart - 1; } this.log("indexStart= " + indexStart); this.log("htmlText.length= " + htmlText.length()); if (indexStart > 0) { viewstateTmp = htmlText.substring(indexStart + 20, indexStart + tokenLength); this.log("\n\n\n"); this.log("\n\n\nviewstateTmp = " + viewstateTmp); this.log("tokenLength = " + tokenLength); this.log("\n\n\n"); int indexEnd = viewstateTmp.indexOf("\" />"); this.log("\nindexEnd = " + indexEnd); if (indexEnd < 0) { return; } viewstateTmp = viewstateTmp.substring(0, indexEnd); this.log("\n***--- Length=" + viewstateTmp.length() + "\nViewstate-Ende-20=" + viewstateTmp.substring(viewstateTmp.length() - 20)); viewstateTmp = viewstateTmp.replace("<", ""); viewstateTmp = viewstateTmp.replace(">", ""); viewstateTmp = viewstateTmp.replace(" ", ""); this.log("--- Viewstate:\nindexOfStart=" + indexStart); if (url.equals(URL_LOGIN_PAGE)) { this.VIEWSTATE_LOGIN = viewstateTmp; this.log("--- \nVIEWSTATE_LOGIN = " + this.VIEWSTATE_LOGIN); } if (url.equals(URL_SEND_PAGE)) { this.VIEWSTATE_SEND = viewstateTmp; this.log("--- \nVIEWSTATE_SEND = " + this.VIEWSTATE_SEND); } } } else { this.log("no viewstate needed"); return; } } private static String getHeaders(final Header[] headers) { String ret = "\n------------\nheaders=\n"; for (Header h : headers) { ret += "\n *** " + h.getName() + ": " + h.getValue(); } ret += "\nend of headers\n------------\n"; return ret; } /** * central logger * * @param message */ private void log(final String message) { // Log.d(TAG, message); } }