lv.vizzual.numuri.service.operators.LVDataProvider.java Source code

Java tutorial

Introduction

Here is the source code for lv.vizzual.numuri.service.operators.LVDataProvider.java

Source

/**
 * This software is released under GPLv3 licence. For
 * further information regarding GPL licence, please visit
 * http://www.gnu.org/licenses/gpl.html
 */
package lv.vizzual.numuri.service.operators;

import android.text.Html;
import android.util.Log;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lv.vizzual.numuri.R;
import lv.vizzual.numuri.service.error.RequestLimitReachedException;
import lv.vizzual.numuri.service.http.HttpProvider;
import lv.vizzual.numuri.service.http.Request;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

public class LVDataProvider implements DataProvider {
    private static final String TAG = "LVDataProvider";
    private static final String PREFIX_LV = "+371";
    private static final String URL = "http://www.numuri.lv/default.aspx";
    private static final int SERVICE_SLEEP_TIMEOUT = 14 * 1000;
    private HttpProvider httpProvider = new HttpProvider();
    private ChallengeProvider challenge;

    public String getNetworkProviderName(String number) throws IOException {
        if (challenge == null) {
            challenge = new ChallengeProvider();
        }

        String networkProvider = null;

        Request req = getRequest(number);
        httpProvider.processRequest(req);
        if (req.isSuccess()) {
            String response = req.getResult();
            networkProvider = extractNetworkProvider(response);

            try {
                Thread.sleep(SERVICE_SLEEP_TIMEOUT);
            } catch (InterruptedException ignored) {
            }
        } else {
            String message = "request failed";
            Log.d(TAG, message);
            throw new IOException(message);
        }

        return networkProvider;
    }

    public int getNetworkProviderIcon(String provider) {
        int icon = -1;

        if (provider.equalsIgnoreCase("Latvijas Mobilais Telefons")) {
            icon = R.drawable.logo_lmt;
        } else if (provider.equalsIgnoreCase("BITE Latvija")) {
            icon = R.drawable.logo_bite;
        } else if (provider.equalsIgnoreCase("IZZI")) {
            icon = R.drawable.logo_izzi;
        } else if (provider.equalsIgnoreCase("Lattelecom")) {
            icon = R.drawable.logo_lattelecom;
        } else if (provider.equalsIgnoreCase("Tele2")) {
            icon = R.drawable.logo_tele2;
        } else if (provider.equalsIgnoreCase("Telekom Baltija")) {
            icon = R.drawable.logo_triatel;
        } else if (provider.equalsIgnoreCase("ZetCOM")) {
            icon = R.drawable.logo_amigo;
        }

        return icon;
    }

    public String cleanNumber(String number) {
        if (number != null) {
            number = number.replace(" ", "");
            number = number.replace("-", "");
            number = number.replace(".", "");
        }
        return number;
    }

    private String extractNetworkProvider(String page) {
        String provider = null;

        if (page.contains("Mintes laik? var veikt tikai 5 pieprasjumus!")) {
            throw new RequestLimitReachedException();
        }

        String exp = "Pakalpojuma nodroin?t?js </td><td><b>(.*?)</b>";
        Pattern pattern = Pattern.compile(exp, Pattern.DOTALL | Pattern.UNIX_LINES);
        Matcher matcher = pattern.matcher(page);
        if (matcher.find()) {
            String providerHTML = matcher.group(1);
            provider = Html.fromHtml(providerHTML).toString();
        }

        return cleanNetworkProvider(provider);
    }

    private Request getRequest(String number) {
        number = number.replace(PREFIX_LV, "").trim();
        number = cleanNumber(number);

        Request req = new Request();
        req.setUrl(URL);
        req.setType(Request.TYPE_POST);

        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("__VIEWSTATE", "DAwADgEBDW51c2E6a2V5RmllbGQA"));
        params.add(new BasicNameValuePair("nusa:id_txtBox_" + challenge.getChallengeField(), number));
        params.add(new BasicNameValuePair("nusa:id_txtBox_" + challenge.getChallengeAnswer(), number));
        params.add(new BasicNameValuePair("nusa:keyField", challenge.getChallengeKey()));
        params.add(new BasicNameValuePair("__EVENTTARGET", "nusa:nusaBtnDetermineNumber"));
        params.add(new BasicNameValuePair("__EVENTARGUMENT", ""));
        req.setData(params);

        List<NameValuePair> headers = new ArrayList<NameValuePair>();
        headers.add(new BasicNameValuePair("User-Agent",
                "Mozilla/5.0 (X11; U; Linux i686; lv-LV; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8"));
        headers.add(new BasicNameValuePair("Host", "www.numuri.lv"));
        headers.add(new BasicNameValuePair("Referer", URL));
        req.setHeaders(headers);

        return req;
    }

    private String cleanNetworkProvider(String provider) {
        if (provider != null) {
            provider = provider.replace("A/S \"", "");
            provider = provider.replace("SIA \"", "");
            provider = provider.replace("Fili?le \"", "");

            if (provider.endsWith("\"") && provider.length() > 1) {
                provider = provider.substring(0, provider.length() - 1);
            }
        }
        return provider;
    }

    public boolean canProcessNumber(String number) {
        boolean canProcess = true;

        // ignore if does not start with country code for Latvia
        if (number.startsWith(PREFIX_PLUS)) {
            if (!number.startsWith(PREFIX_LV)) {
                canProcess = false;
            }
        } else {
            number.replace(PREFIX_LV, "").trim();
            number = cleanNumber(number);
            // in Latvia numbers are shorter than 8 signs
            if (number.length() > 8) {
                canProcess = false;
            }
        }
        return canProcess;
    }

    private class ChallengeProvider {
        private String challengeField = null;
        private String challengeKey = null;
        private String challengeAnswer = null;

        public ChallengeProvider() throws IOException {
            // initialize challenge
            Request req = getChallengeRequest();
            httpProvider.processRequest(req);

            if (req.isSuccess()) {
                String response = req.getResult();

                challengeField = retrieveChallengeField(response);
                challengeKey = retrieveChallengeKey(response);
                challengeAnswer = retrieveChallengeAnswer(challengeKey);
            } else {
                String message = "challenge request failed";
                Log.d(TAG, message);
                throw new RuntimeException(message);
            }
        }

        private Request getChallengeRequest() {
            Request req = new Request();
            req.setUrl(URL);
            req.setType(Request.TYPE_GET);
            return req;
        }

        private String retrieveChallengeAnswer(String key) {
            int magic = 43;
            int fieldCount = 20;

            for (int i = 0; i < key.length(); i++) {
                magic += key.charAt(i);
            }
            return String.valueOf(magic % fieldCount);
        }

        private String retrieveChallengeField(String page) {
            String field = null;

            String exp = "\\Qr( document.getElementById('nusa_id_txtBox_\\E(.*?)\\'";
            Pattern pattern = Pattern.compile(exp, Pattern.DOTALL | Pattern.UNIX_LINES);
            Matcher matcher = pattern.matcher(page);
            if (matcher.find()) {
                field = matcher.group(1);
            }

            return field;
        }

        private String retrieveChallengeKey(String page) {
            String key = null;

            String exp = "id=\"nusa_keyField\" type=\"hidden\" value=\"(.*?)\"";
            Pattern pattern = Pattern.compile(exp, Pattern.DOTALL | Pattern.UNIX_LINES);
            Matcher matcher = pattern.matcher(page);
            if (matcher.find()) {
                key = matcher.group(1);
            }

            return key;
        }

        public String getChallengeField() {
            return challengeField;
        }

        public String getChallengeKey() {
            return challengeKey;
        }

        public String getChallengeAnswer() {
            return challengeAnswer;
        }
    }
}