<commit_before>package cgeo.geocaching.connector.gc;

import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.TextUtils;

import ch.boye.httpclientandroidlib.HttpResponse;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;

import android.graphics.drawable.BitmapDrawable;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public abstract class Login {

    private static final String DEFAULT_CUSTOM_DATE_FORMAT = "MM/dd/yyyy";

    private final static String ENGLISH = "<a href=\"#\">English&#9660;</a>";

    // false = not logged in
    private static boolean actualLoginStatus = false;
    private static String actualUserName = StringUtils.EMPTY;
    private static int actualCachesFound = -1;
    private static String actualStatus = StringUtils.EMPTY;

    private final static Map<String, SimpleDateFormat> GC_CUSTOM_DATE_FORMATS;
    public static final String LANGUAGE_CHANGE_URI = "http://www.geocaching.com/my/souvenirs.aspx";

    static {
        final String[] formats = new String[] {
                DEFAULT_CUSTOM_DATE_FORMAT,
                "yyyy-MM-dd",
                "yyyy/MM/dd",
                "dd/MMM/yyyy",
                "MMM/dd/yyyy",
                "dd MMM yy",
                "dd/MM/yyyy"
        };

        final Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();

        for (final String format : formats) {
            map.put(format, new SimpleDateFormat(format, Locale.ENGLISH));
        }

        GC_CUSTOM_DATE_FORMATS = Collections.unmodifiableMap(map);
    }

    public static StatusCode login() {
        return login(true);
    }

    private static StatusCode login(boolean retry) {
        final ImmutablePair<String, String> login = Settings.getGcLogin();

        if (StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) {
            clearLoginInfo();
            Log.e("Login.login: No login information stored");
            return StatusCode.NO_LOGIN_INFO_STORED;
        }

        Login.setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_working));
        HttpResponse loginResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx");
        String loginData = Network.getResponseData(loginResponse);
        if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) {
            return StatusCode.MAINTENANCE;
        }

        if (StringUtils.isBlank(loginData)) {
            Log.e("Login.login: Failed to retrieve login page (1st)");
            return StatusCode.CONNECTION_FAILED; // no loginpage
        }

        if (Login.getLoginStatus(loginData)) {
            Log.i("Already logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')');
            Login.switchToEnglish(loginData);
            return StatusCode.NO_ERROR; // logged in
        }

        Cookies.clearCookies();
        Settings.setCookieStore(null);

        final Parameters params = new Parameters(
                "__EVENTTARGET", "",
                "__EVENTARGUMENT", "",
                "ctl00$ContentBody$tbUsername", login.left,
                "ctl00$ContentBody$tbPassword", login.right,
                "ctl00$ContentBody$cbRememberMe", "on",
                "ctl00$ContentBody$btnSignIn", "Login");
        final String[] viewstates = Login.getViewstates(loginData);
        if (isEmpty(viewstates)) {
            Log.e("Login.login: Failed to find viewstates");
            return StatusCode.LOGIN_PARSE_ERROR; // no viewstates
        }
        Login.putViewstates(params, viewstates);

        loginResponse = Network.postRequest("https://www.geocaching.com/login/default.aspx", params);
        loginData = Network.getResponseData(loginResponse);

        if (loginData == null || StringUtils.isBlank(loginData)) {
            Log.e("Login.login: Failed to retrieve login page (2nd)");
            // FIXME: should it be CONNECTION_FAILED to match the first attempt?
            return StatusCode.COMMUNICATION_ERROR; // no login page
        }

        if (Login.getLoginStatus(loginData)) {
            Log.i("Successfully logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')');<commit_msg>refactoring: add assertion instead of explicit null check<commit_after>package cgeo.geocaching.connector.gc;

import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MatcherWrapper;
import cgeo.geocaching.utils.TextUtils;

import ch.boye.httpclientandroidlib.HttpResponse;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;

import android.graphics.drawable.BitmapDrawable;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public abstract class Login {

    private static final String DEFAULT_CUSTOM_DATE_FORMAT = "MM/dd/yyyy";

    private final static String ENGLISH = "<a href=\"#\">English&#9660;</a>";

    // false = not logged in
    private static boolean actualLoginStatus = false;
    private static String actualUserName = StringUtils.EMPTY;
    private static int actualCachesFound = -1;
    private static String actualStatus = StringUtils.EMPTY;

    private final static Map<String, SimpleDateFormat> GC_CUSTOM_DATE_FORMATS;
    public static final String LANGUAGE_CHANGE_URI = "http://www.geocaching.com/my/souvenirs.aspx";

    static {
        final String[] formats = new String[] {
                DEFAULT_CUSTOM_DATE_FORMAT,
                "yyyy-MM-dd",
                "yyyy/MM/dd",
                "dd/MMM/yyyy",
                "MMM/dd/yyyy",
                "dd MMM yy",
                "dd/MM/yyyy"
        };

        final Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();

        for (final String format : formats) {
            map.put(format, new SimpleDateFormat(format, Locale.ENGLISH));
        }

        GC_CUSTOM_DATE_FORMATS = Collections.unmodifiableMap(map);
    }

    public static StatusCode login() {
        return login(true);
    }

    private static StatusCode login(boolean retry) {
        final ImmutablePair<String, String> login = Settings.getGcLogin();

        if (StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) {
            clearLoginInfo();
            Log.e("Login.login: No login information stored");
            return StatusCode.NO_LOGIN_INFO_STORED;
        }

        Login.setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_working));
        HttpResponse loginResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx");
        String loginData = Network.getResponseData(loginResponse);
        if (loginResponse != null && loginResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(loginData, GCConstants.PATTERN_MAINTENANCE)) {
            return StatusCode.MAINTENANCE;
        }

        if (StringUtils.isBlank(loginData)) {
            Log.e("Login.login: Failed to retrieve login page (1st)");
            return StatusCode.CONNECTION_FAILED; // no loginpage
        }

        if (Login.getLoginStatus(loginData)) {
            Log.i("Already logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')');
            Login.switchToEnglish(loginData);
            return StatusCode.NO_ERROR; // logged in
        }

        Cookies.clearCookies();
        Settings.setCookieStore(null);

        final Parameters params = new Parameters(
                "__EVENTTARGET", "",
                "__EVENTARGUMENT", "",
                "ctl00$ContentBody$tbUsername", login.left,
                "ctl00$ContentBody$tbPassword", login.right,
                "ctl00$ContentBody$cbRememberMe", "on",
                "ctl00$ContentBody$btnSignIn", "Login");
        final String[] viewstates = Login.getViewstates(loginData);
        if (isEmpty(viewstates)) {
            Log.e("Login.login: Failed to find viewstates");
            return StatusCode.LOGIN_PARSE_ERROR; // no viewstates
        }
        Login.putViewstates(params, viewstates);

        loginResponse = Network.postRequest("https://www.geocaching.com/login/default.aspx", params);
        loginData = Network.getResponseData(loginResponse);

        if (StringUtils.isBlank(loginData)) {
            Log.e("Login.login: Failed to retrieve login page (2nd)");
            // FIXME: should it be CONNECTION_FAILED to match the first attempt?
            return StatusCode.COMMUNICATION_ERROR; // no login page
        }
        assert loginData != null;  // Caught above

        if (Login.getLoginStatus(loginData)) {
            Log.i("Successfully logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')');
{'fraction_non_alphanumeric': 0.10843617236496055, 'fraction_numerical': 0.004248432126239126, 'mean_word_length': 2.9171949286846277, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 4, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '127709', 'n_tokens_mistral': 2860, 'n_tokens_neox': 2776, 'n_words': 566}