Java tutorial
/* * This file is part of Ermete SMS. * * Ermete SMS 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. * * Ermete SMS 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 Ermete SMS. If not, see <http://www.gnu.org/licenses/>. * */ package com.googlecode.esms.provider; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import com.googlecode.esms.account.Account; import com.googlecode.esms.account.AccountConnector; import com.googlecode.esms.message.Base64; import com.googlecode.esms.message.SMS; public class Vodafone extends Account { private static final long serialVersionUID = 1L; static final String PROVIDER = "Vodafone"; static final String CHECK_USER = "https://www.vodafone.it/190/trilogy/jsp/utility/checkUser.jsp"; static final String DO_LOGIN = "https://www.vodafone.it/190/trilogy/jsp/login.do"; // static final String DO_LOGOUT = // "http://www.vodafone.it/190/trilogy/jsp/logout.do"; static final String DO_SWAPSIM = "https://www.vodafone.it/190/trilogy/jsp/swapSim.do"; static final String DO_PRECHECK = "https://www.vodafone.it/190/fsms/precheck.do?channel=VODAFONE_DW"; static final String DO_PREPARE = "https://www.vodafone.it/190/fsms/prepare.do?channel=VODAFONE_DW"; static final String DO_SEND = "https://www.vodafone.it/190/fsms/send.do?channel=VODAFONE_DW"; static final Pattern XML_DOCUMENT = Pattern.compile("<\\?xml.*<\\/root>"); boolean loggedIn; boolean isConsumer; boolean isCorporate; boolean isBlocked; String senderCurrent; List<String> senderList; String usernameCurrent; public Vodafone(AccountConnector connector) { super(connector); label = PROVIDER; provider = PROVIDER; limit = 10; loggedIn = false; senderList = new LinkedList<String>(); } @Override protected void initAccountConnector() { httpClient.getParams().setParameter("http.protocol.allow-circular-redirects", true); httpClient.getParams().setParameter("http.useragent", "Vodafone_DW"); } @Override public int calcRemaining(int length) { if (length == 0) { return 0; } else if (length <= 160) { return 160 - length; } else if (length <= 307) { return 307 - length; } else if (length <= 360) { return 360 - length; } else { return 360 - length; } } @Override public int calcFragments(int length) { if (length == 0) { return 0; } else if (length <= 160) { return 1; } else if (length <= 307) { return 2; } else if (length <= 360) { return 3; } else { return 0; } } @Override protected void updateCount() { Calendar prev = Calendar.getInstance(); prev.setTime(countDate); Calendar curr = Calendar.getInstance(); curr.setTime(new Date()); if (prev.get(Calendar.YEAR) < curr.get(Calendar.YEAR) || prev.get(Calendar.MONTH) < curr.get(Calendar.MONTH) || prev.get(Calendar.DATE) < curr.get(Calendar.DATE)) { count = 0; countDate = new Date(); } } @Override public Result login() { try { if (loggedIn) { if (usernameCurrent.equalsIgnoreCase(username)) return Result.SUCCESSFUL; else if (!doLogout()) return Result.LOGOUT_ERROR; } if (doLogin()) { if (isCorporate || isBlocked) return Result.UNSUPPORTED_ERROR; else return Result.SUCCESSFUL; } else { return Result.LOGIN_ERROR; } } catch (JDOMException je) { je.printStackTrace(); return Result.PROVIDER_ERROR; } catch (Exception e) { e.printStackTrace(); return Result.NETWORK_ERROR; } } @Override public Result logout() { try { if (!loggedIn) { return Result.SUCCESSFUL; } if (doLogout()) { return Result.SUCCESSFUL; } else { return Result.LOGOUT_ERROR; } } catch (JDOMException je) { je.printStackTrace(); return Result.PROVIDER_ERROR; } catch (Exception e) { e.printStackTrace(); return Result.NETWORK_ERROR; } } @Override public List<String> getSenderList() { if (loggedIn) return senderList; else return null; } @Override public List<Result> send(SMS sms) { int currReceiver = 0; int totReceivers = sms.getReceivers().size(); List<Result> results = new LinkedList<Result>(); for (int r = 0; r < totReceivers; ++r) results.add(Result.UNKNOWN_ERROR); try { Result login = login(); if (login != Result.SUCCESSFUL) { results.set(0, login); return results; } if (!senderCurrent.equalsIgnoreCase(sender)) { if (!doSwapSIM()) { results.set(0, Result.SENDER_ERROR); return results; } } for (int r = 0; r < totReceivers; ++r) { currReceiver = r; if (sms.getCaptchaText() == null || sms.getCaptchaText() == "") { int precheck = doPrecheck(); if (precheck != 0) { results.set(r, getResult(precheck)); return results; } int prepare = doPrepare(sms, r); if (prepare != 0) { results.set(r, getResult(prepare)); return results; } if (sms.getCaptchaArray() != null) { results.set(r, Result.CAPTCHA_NEEDED); return results; } } // filter wrong CAPTCHA characters String captchaText = sms.getCaptchaText(); if (captchaText != null) { captchaText.replaceAll("[^1-9A-NP-Za-np-z]*", ""); sms.setCaptchaText(captchaText); } int send = doSend(sms, r); if (send != 0) { results.set(r, getResult(send)); return results; } if (sms.getCaptchaArray() != null) { results.set(r, Result.CAPTCHA_NEEDED); return results; } updateCount(); count += calcFragments(sms.getMessage().length()); results.set(r, Result.SUCCESSFUL); } } catch (JDOMException je) { je.printStackTrace(); results.set(currReceiver, Result.PROVIDER_ERROR); } catch (Exception e) { e.printStackTrace(); results.set(currReceiver, Result.NETWORK_ERROR); } return results; } private void checkUser() throws ClientProtocolException, IOException, IllegalStateException, JDOMException { HttpGet request = new HttpGet(CHECK_USER); HttpResponse response = httpClient.execute(request, httpContext); Document document = getXMLDocument(response.getEntity().getContent()); response.getEntity().consumeContent(); Element root = document.getRootElement(); Element liChild = root.getChild("logged-in"); loggedIn = liChild.getValue().equals("true"); senderCurrent = null; senderList.clear(); if (loggedIn) { Element userChild = root.getChild("user"); isConsumer = userChild.getChild("is-consumer").getValue().equals("true"); isCorporate = userChild.getChild("is-corporate").getValue().equals("true"); isBlocked = userChild.getChild("is-blocked").getValue().equals("true"); senderCurrent = userChild.getChild("current-msisdn").getValue(); senderList.add(senderCurrent); // TODO support other SIM // Element asChild = userChild.getChild("all-sims"); // @SuppressWarnings("unchecked") // List<Element> mChildren = asChild.getChildren("msisdn"); // for (Element mChild : mChildren) senderList.add(mChild.getValue()); usernameCurrent = root.getChild("security").getChild("username").getValue(); } } private boolean doLogin() throws ClientProtocolException, IOException, IllegalStateException, JDOMException { HttpPost request = new HttpPost(DO_LOGIN); List<NameValuePair> requestData = new ArrayList<NameValuePair>(); requestData.add(new BasicNameValuePair("username", username)); requestData.add(new BasicNameValuePair("password", password)); request.setEntity(new UrlEncodedFormEntity(requestData, HTTP.UTF_8)); HttpResponse response = httpClient.execute(request, httpContext); response.getEntity().consumeContent(); checkUser(); if (loggedIn && usernameCurrent.equalsIgnoreCase(username)) return true; else return false; } private boolean doLogout() throws ClientProtocolException, IOException, IllegalStateException, JDOMException { // HttpGet request = new HttpGet(DO_LOGOUT); // HttpResponse response = httpClient.execute(request, httpContext); // response.getEntity().consumeContent(); // this is enough cookieStore.clear(); checkUser(); if (!loggedIn) return true; else return false; } private Result getResult(int code) { switch (code) { case 107: return Result.LIMIT_ERROR; case 113: return Result.RECEIVER_ERROR; case 109: case 112: // "Numero destinatario con caratteri non validi" return Result.MESSAGE_ERROR; case 104: // "Servizio non disponibile" return Result.PROVIDER_ERROR; default: return Result.UNKNOWN_ERROR; } } private boolean doSwapSIM() throws ClientProtocolException, IOException, IllegalStateException, JDOMException { HttpPost request = new HttpPost(DO_SWAPSIM); List<NameValuePair> requestData = new ArrayList<NameValuePair>(); requestData.add(new BasicNameValuePair("ty_sim", sender)); requestData.add(new BasicNameValuePair("swap_sim_link", sender)); request.setEntity(new UrlEncodedFormEntity(requestData, HTTP.UTF_8)); HttpResponse response = httpClient.execute(request, httpContext); response.getEntity().consumeContent(); checkUser(); if (loggedIn && usernameCurrent.equalsIgnoreCase(username) && senderCurrent.equalsIgnoreCase(sender)) return true; else return false; } private int doPrecheck() throws ClientProtocolException, IOException, JDOMException { HttpGet request = new HttpGet(DO_PRECHECK); HttpResponse response = httpClient.execute(request, httpContext); // BufferedReader testReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); // String line; while ((line = testReader.readLine()) != null) System.out.println(line); Document document = getXMLDocument(response.getEntity().getContent()); response.getEntity().consumeContent(); Element root = document.getRootElement(); @SuppressWarnings("unchecked") List<Element> children = root.getChildren("e"); int status = 0, errorcode = 0; for (Element child : children) { if (child.getAttributeValue("n").equals("STATUS")) status = Integer.parseInt(child.getAttributeValue("v")); if (child.getAttributeValue("n").equals("ERRORCODE")) errorcode = Integer.parseInt(child.getAttributeValue("v")); } if (status != 1) return errorcode; return 0; } private int doPrepare(SMS sms, int id) throws IOException, IllegalStateException, JDOMException { HttpPost request = new HttpPost(DO_PREPARE); List<NameValuePair> requestData = new ArrayList<NameValuePair>(); requestData .add(new BasicNameValuePair("receiverNumber", stripPrefix(sms.getReceivers().get(id).getNumber()))); requestData.add(new BasicNameValuePair("message", sms.getMessage())); request.setEntity(new UrlEncodedFormEntity(requestData, HTTP.UTF_8)); HttpResponse response = httpClient.execute(request, httpContext); Document document = getXMLDocument(response.getEntity().getContent()); response.getEntity().consumeContent(); Element root = document.getRootElement(); @SuppressWarnings("unchecked") List<Element> children = root.getChildren("e"); int status = 0, errorcode = 0; for (Element child : children) { if (child.getAttributeValue("n").equals("STATUS")) status = Integer.parseInt(child.getAttributeValue("v")); if (child.getAttributeValue("n").equals("ERRORCODE")) errorcode = Integer.parseInt(child.getAttributeValue("v")); if (child.getAttributeValue("n").equals("CODEIMG")) { sms.setCaptchaArray(Base64.decode(child.getValue())); return 0; } } if (status != 1) return errorcode; return 0; } private int doSend(SMS sms, int id) throws IOException, IllegalStateException, JDOMException { HttpPost request = new HttpPost(DO_SEND); List<NameValuePair> requestData = new ArrayList<NameValuePair>(); requestData.add(new BasicNameValuePair("verifyCode", sms.getCaptchaText())); requestData .add(new BasicNameValuePair("receiverNumber", stripPrefix(sms.getReceivers().get(id).getNumber()))); requestData.add(new BasicNameValuePair("message", sms.getMessage())); request.setEntity(new UrlEncodedFormEntity(requestData, HTTP.UTF_8)); HttpResponse response = httpClient.execute(request, httpContext); Document document = getXMLDocument(response.getEntity().getContent()); response.getEntity().consumeContent(); Element root = document.getRootElement(); @SuppressWarnings("unchecked") List<Element> children = root.getChildren("e"); int status = 0, errorcode = 0; // String returnmsg = null; for (Element child : children) { if (child.getAttributeValue("n").equals("STATUS")) status = Integer.parseInt(child.getAttributeValue("v")); if (child.getAttributeValue("n").equals("ERRORCODE")) errorcode = Integer.parseInt(child.getAttributeValue("v")); // if (child.getAttributeValue("n").equals("RETURNMSG")) // returnmsg = child.getValue(); if (child.getAttributeValue("n").equals("CODEIMG")) { sms.setCaptchaArray(Base64.decode(child.getValue())); return 0; } } if (status != 1) return errorcode; sms.setCaptchaArray(null); return 0; } /** * Remove country code prefix, if present. * @param receiver Phone number with or without CC prefix. * @return Phone number without CC prefix. */ private String stripPrefix(String receiver) { final String PREFIX = "39"; receiver = receiver.replaceAll("[^0-9\\+]*", ""); int lNumber = receiver.length(); String pPlus = "+" + PREFIX; int lPlus = pPlus.length(); if (lNumber > lPlus && receiver.substring(0, lPlus).equals(pPlus)) { return receiver.substring(lPlus); } String pZero = "00" + PREFIX; int lZero = pZero.length(); if (lNumber > lZero && receiver.substring(0, lZero).equals(pZero)) { return receiver.substring(lZero); } return receiver; } /** * Get XML document, removing leading spaces and trailing "junk". * @param input Stream to be read. * @return XML document model. */ private Document getXMLDocument(InputStream input) throws IOException, JDOMException { String source = convertStreamToString(input); source = source.replaceAll("\\n", ""); Matcher matcher = XML_DOCUMENT.matcher(source); if (matcher.find()) { return new SAXBuilder().build(new StringReader(matcher.group())); } else { throw new JDOMException(); } } /** * Convert any stream to a string. * @param input Stream to be read. * @return String representation of the stream. */ private String convertStreamToString(InputStream input) throws IOException { if (input != null) { Writer writer = new StringWriter(); char[] buffer = new char[1024]; Reader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); int n; while ((n = reader.read(buffer)) != -1) writer.write(buffer, 0, n); input.close(); return writer.toString(); } else { return ""; } } }