package cgeo.geocaching.connector.ec; import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import cgeo.geocaching.connector.AbstractLogin; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Credentials; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.JsonUtils; import cgeo.geocaching.utils.Log; import android.app.Application; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.io.IOException; import com.fasterxml.jackson.databind.JsonNode; import org.apache.commons.lang3.StringUtils; public class ECLogin extends AbstractLogin { private String sessionId = null; private ECLogin() { // singleton } private static class SingletonHolder { @NonNull private static final ECLogin INSTANCE = new ECLogin(); } @NonNull public static ECLogin getInstance() { return SingletonHolder.INSTANCE; } @Override @NonNull protected StatusCode login(final boolean retry) { return login(retry, Settings.getCredentials(ECConnector.getInstance())); } @Override @NonNull protected StatusCode login(final boolean retry, @NonNull final Credentials credentials) { if (credentials.isInvalid()) { clearLoginInfo(); Log.w("ECLogin.login: No login information stored"); return StatusCode.NO_LOGIN_INFO_STORED; } setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_working)); final Parameters params = new Parameters("user", credentials.getUserName(), "pass", credentials.getPassword()); final String loginData = Network.getResponseData(Network.postRequest("https://extremcaching.com/exports/apilogin.php", params)); if (StringUtils.isBlank(loginData)) { Log.e("ECLogin.login: Failed to retrieve login data"); return StatusCode.CONNECTION_FAILED_EC; // no login page } assert loginData != null; if (loginData.contains("Wrong username or password")) { // hardcoded in English Log.i("Failed to log in Extremcaching.com as " + credentials.getUserName() + " because of wrong username/password"); return StatusCode.WRONG_LOGIN_DATA; // wrong login } if (getLoginStatus(loginData)) { Log.i("Successfully logged in Extremcaching.com as " + credentials.getUserName()); return StatusCode.NO_ERROR; // logged in } Log.i("Failed to log in Extremcaching.com as " + credentials.getUserName() + " for some unknown reason"); if (retry) { return login(false, credentials); } return StatusCode.UNKNOWN_ERROR; // can't login } /** * Check if the user has been logged in when he retrieved the data. * * @return {@code true} if user is logged in, {@code false} otherwise */ private boolean getLoginStatus(@Nullable final String data) { if (StringUtils.isBlank(data) || StringUtils.equals(data, "[]")) { Log.e("ECLogin.getLoginStatus: No or empty data given"); return false; } assert data != null; final Application application = CgeoApplication.getInstance(); setActualStatus(application.getString(R.string.init_login_popup_ok)); try { final JsonNode json = JsonUtils.reader.readTree(data); final String sid = json.get("sid").asText(); if (!StringUtils.isBlank(sid)) { sessionId = sid; setActualLoginStatus(true); setActualUserName(json.get("username").asText()); setActualCachesFound(json.get("found").asInt()); return true; } resetLoginStatus(); } catch (IOException | NullPointerException e) { Log.e("ECLogin.getLoginStatus", e); } setActualStatus(application.getString(R.string.init_login_popup_failed)); return false; } @Override protected void resetLoginStatus() { sessionId = null; setActualLoginStatus(false); } public String getSessionId() { if (!StringUtils.isBlank(sessionId) || login() == StatusCode.NO_ERROR) { return sessionId; } return StringUtils.EMPTY; } }