From 3719de7a754c103a3e841ec68ba8af31eda30d76 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 16 Dec 2013 15:09:26 +0100 Subject: rename Login to GCLogin * easier to differentiate, as there are other login providers now --- main/src/cgeo/geocaching/LogTrackableActivity.java | 8 +- main/src/cgeo/geocaching/SearchResult.java | 4 +- .../cgeo/geocaching/connector/gc/GCConnector.java | 12 +- .../geocaching/connector/gc/GCLoggingManager.java | 2 +- main/src/cgeo/geocaching/connector/gc/GCLogin.java | 517 +++++++++++++++++++++ main/src/cgeo/geocaching/connector/gc/GCMap.java | 2 +- .../src/cgeo/geocaching/connector/gc/GCParser.java | 76 +-- main/src/cgeo/geocaching/connector/gc/Login.java | 517 --------------------- .../cgeo/geocaching/export/FieldnoteExport.java | 12 +- main/src/cgeo/geocaching/maps/CGeoMap.java | 6 +- .../settings/CheckGcCredentialsPreference.java | 8 +- main/src/cgeo/geocaching/settings/Settings.java | 4 +- .../cgeo/geocaching/settings/SettingsActivity.java | 6 +- 13 files changed, 587 insertions(+), 587 deletions(-) create mode 100644 main/src/cgeo/geocaching/connector/gc/GCLogin.java delete mode 100644 main/src/cgeo/geocaching/connector/gc/Login.java (limited to 'main/src') diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java index e549fdc..5246fa9 100644 --- a/main/src/cgeo/geocaching/LogTrackableActivity.java +++ b/main/src/cgeo/geocaching/LogTrackableActivity.java @@ -4,7 +4,7 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.connector.gc.GCParser; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; @@ -76,7 +76,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat showToast(res.getString(R.string.info_log_type_changed)); } - if (Login.isEmpty(viewstates)) { + if (GCLogin.isEmpty(viewstates)) { if (attempts < 2) { showToast(res.getString(R.string.err_log_load_data_again)); new LoadDataThread().start(); @@ -200,7 +200,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat possibleLogTypes = Trackable.getPossibleLogTypes(); } - if (Login.isEmpty(viewstates)) { + if (GCLogin.isEmpty(viewstates)) { buttonPost.setEnabled(false); buttonPost.setOnTouchListener(null); buttonPost.setOnClickListener(null); @@ -294,7 +294,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/track/log.aspx", params)); - viewstates = Login.getViewstates(page); + viewstates = GCLogin.getViewstates(page); final List typesPre = GCParser.parseTypes(page); if (CollectionUtils.isNotEmpty(typesPre)) { diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index 0bdf6c6..04ac3e0 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -1,6 +1,6 @@ package cgeo.geocaching; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; @@ -173,7 +173,7 @@ public class SearchResult implements Parcelable { } public void setViewstates(String[] viewstates) { - if (Login.isEmpty(viewstates)) { + if (GCLogin.isEmpty(viewstates)) { return; } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index 6a61405..58094ed 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -297,11 +297,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, @Override public boolean login(Handler handler, Context fromActivity) { // login - final StatusCode status = Login.login(); + final StatusCode status = GCLogin.login(); if (status == StatusCode.NO_ERROR) { CgeoApplication.getInstance().checkLogin = false; - Login.detectGcCustomDate(); + GCLogin.detectGcCustomDate(); } if (CgeoApplication.getInstance().showLoginToast && handler != null) { @@ -318,22 +318,22 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, @Override public String getUserName() { - return Login.getActualUserName(); + return GCLogin.getActualUserName(); } @Override public int getCachesFound() { - return Login.getActualCachesFound(); + return GCLogin.getActualCachesFound(); } @Override public String getLoginStatusString() { - return Login.getActualStatus(); + return GCLogin.getActualStatus(); } @Override public boolean isLoggedIn() { - return Login.isActualLoginStatus(); + return GCLogin.isActualLoginStatus(); } @Override diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java index 8bed2ea..c618110 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java @@ -60,7 +60,7 @@ public class GCLoggingManager implements ILoggingManager, LoaderManager.LoaderCa hasLoaderError = true; } else { - viewstates = Login.getViewstates(page); + viewstates = GCLogin.getViewstates(page); trackables = GCParser.parseTrackableLog(page); possibleLogTypes = GCParser.parseTypes(page); diff --git a/main/src/cgeo/geocaching/connector/gc/GCLogin.java b/main/src/cgeo/geocaching/connector/gc/GCLogin.java new file mode 100644 index 0000000..53be668 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/gc/GCLogin.java @@ -0,0 +1,517 @@ +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 org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +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 GCLogin { + + private static final String DEFAULT_CUSTOM_DATE_FORMAT = "MM/dd/yyyy"; + + private final static String ENGLISH = "English▼"; + + // 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 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 map = new HashMap(); + + 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 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; + } + + GCLogin.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 (GCLogin.getLoginStatus(loginData)) { + Log.i("Already logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')'); + GCLogin.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 = GCLogin.getViewstates(loginData); + if (isEmpty(viewstates)) { + Log.e("Login.login: Failed to find viewstates"); + return StatusCode.LOGIN_PARSE_ERROR; // no viewstates + } + GCLogin.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 (GCLogin.getLoginStatus(loginData)) { + Log.i("Successfully logged in Geocaching.com as " + login.left + " (" + Settings.getMemberStatus() + ')'); + + GCLogin.switchToEnglish(loginData); + Settings.setCookieStore(Cookies.dumpCookieStore()); + + return StatusCode.NO_ERROR; // logged in + } + + if (loginData.contains("Your username/password combination does not match.")) { + Log.i("Failed to log in Geocaching.com as " + login.left + " because of wrong username/password"); + return StatusCode.WRONG_LOGIN_DATA; // wrong login + } + + if (loginData.contains("You must validate your account before you can log in.")) { + Log.i("Failed to log in Geocaching.com as " + login.left + " because account needs to be validated first"); + return StatusCode.UNVALIDATED_ACCOUNT; + } + + Log.i("Failed to log in Geocaching.com as " + login.left + " for some unknown reason"); + if (retry) { + GCLogin.switchToEnglish(loginData); + return login(false); + } + + return StatusCode.UNKNOWN_ERROR; // can't login + } + + public static StatusCode logout() { + final HttpResponse logoutResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f"); + final String logoutData = Network.getResponseData(logoutResponse); + if (logoutResponse != null && logoutResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(logoutData, GCConstants.PATTERN_MAINTENANCE)) { + return StatusCode.MAINTENANCE; + } + + resetLoginStatus(); + + return StatusCode.NO_ERROR; + } + + private static void resetLoginStatus() { + Cookies.clearCookies(); + Settings.setCookieStore(null); + + setActualLoginStatus(false); + } + + private static void clearLoginInfo() { + resetLoginStatus(); + + setActualCachesFound(-1); + setActualStatus(CgeoApplication.getInstance().getString(R.string.err_login)); + } + + static void setActualCachesFound(final int found) { + actualCachesFound = found; + } + + public static String getActualStatus() { + return actualStatus; + } + + private static void setActualStatus(final String status) { + actualStatus = status; + } + + public static boolean isActualLoginStatus() { + return actualLoginStatus; + } + + private static void setActualLoginStatus(boolean loginStatus) { + actualLoginStatus = loginStatus; + } + + public static String getActualUserName() { + return actualUserName; + } + + private static void setActualUserName(String userName) { + actualUserName = userName; + } + + public static int getActualCachesFound() { + return actualCachesFound; + } + + /** + * Check if the user has been logged in when he retrieved the data. + * + * @param page + * @return true if user is logged in, false otherwise + */ + public static boolean getLoginStatus(@Nullable final String page) { + if (StringUtils.isBlank(page)) { + Log.e("Login.checkLogin: No page given"); + return false; + } + assert page != null; + + setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_ok)); + + // on every page except login page + setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME)); + if (isActualLoginStatus()) { + setActualUserName(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); + int cachesCount = 0; + try { + cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); + } catch (final NumberFormatException e) { + Log.e("getLoginStatus: bad cache count", e); + } + setActualCachesFound(cachesCount); + Settings.setMemberStatus(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null)); + if ( page.contains(GCConstants.MEMBER_STATUS_RENEW) ) { + Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM); + } + return true; + } + + // login page + setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE)); + if (isActualLoginStatus()) { + setActualUserName(Settings.getUsername()); + // number of caches found is not part of this page + return true; + } + + setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_failed)); + return false; + } + + private static void switchToEnglish(String previousPage) { + if (previousPage != null && previousPage.contains(ENGLISH)) { + Log.i("Geocaching.com language already set to English"); + // get find count + getLoginStatus(Network.getResponseData(Network.getRequest("http://www.geocaching.com/email/"))); + } else { + final String page = Network.getResponseData(Network.getRequest(LANGUAGE_CHANGE_URI)); + getLoginStatus(page); + if (page == null) { + Log.e("Failed to read viewstates to set geocaching.com language"); + } + final Parameters params = new Parameters( + "__EVENTTARGET", "ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem", // switch to english + "__EVENTARGUMENT", ""); + GCLogin.transferViewstates(page, params); + final HttpResponse response = Network.postRequest(LANGUAGE_CHANGE_URI, params, new Parameters("Referer", LANGUAGE_CHANGE_URI)); + if (Network.isSuccess(response)) { + Log.i("changed language on geocaching.com to English"); + } else { + Log.e("Failed to set geocaching.com language to English"); + } + } + } + + public static BitmapDrawable downloadAvatarAndGetMemberStatus() { + try { + final String responseData = StringUtils.defaultString(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/"))); + final String profile = TextUtils.replaceWhitespace(responseData); + + Settings.setMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null)); + if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) { + Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM); + } + + setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""))); + + final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null); + if (null != avatarURL) { + final HtmlImage imgGetter = new HtmlImage("", false, 0, false); + return imgGetter.getDrawable(avatarURL); + } + // No match? There may be no avatar set by user. + Log.d("No avatar set for user"); + } catch (final Exception e) { + Log.w("Error when retrieving user avatar", e); + } + return null; + } + + /** + * Detect user date settings on geocaching.com + */ + public static void detectGcCustomDate() { + + final String result = Network.getResponseData(Network.getRequest("http://www.geocaching.com/account/ManagePreferences.aspx")); + + if (null == result) { + Log.w("Login.detectGcCustomDate: result is null"); + return; + } + + final String customDate = TextUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null); + if (null != customDate) { + Settings.setGcCustomDate(customDate); + } + } + + public static Date parseGcCustomDate(final String input, final String format) throws ParseException { + if (StringUtils.isBlank(input)) { + throw new ParseException("Input is null", 0); + } + + final String trimmed = input.trim(); + + if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) { + try { + return GC_CUSTOM_DATE_FORMATS.get(format).parse(trimmed); + } catch (final ParseException e) { + } + } + + for (final SimpleDateFormat sdf : GC_CUSTOM_DATE_FORMATS.values()) { + try { + return sdf.parse(trimmed); + } catch (final ParseException e) { + } + } + + throw new ParseException("No matching pattern", 0); + } + + public static Date parseGcCustomDate(final String input) throws ParseException { + return parseGcCustomDate(input, Settings.getGcCustomDate()); + } + + public static SimpleDateFormat getCustomGcDateFormat() { + final String format = Settings.getGcCustomDate(); + if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) { + return GC_CUSTOM_DATE_FORMATS.get(format); + } + + return GC_CUSTOM_DATE_FORMATS.get(DEFAULT_CUSTOM_DATE_FORMAT); + } + + /** + * checks if an Array of Strings is empty or not. Empty means: + * - Array is null + * - or all elements are null or empty strings + */ + public static boolean isEmpty(String[] a) { + if (a == null) { + return true; + } + + for (final String s : a) { + if (StringUtils.isNotEmpty(s)) { + return false; + } + } + return true; + } + + /** + * read all viewstates from page + * + * @return String[] with all view states + */ + public static String[] getViewstates(String page) { + // Get the number of viewstates. + // If there is only one viewstate, __VIEWSTATEFIELDCOUNT is not present + + if (page == null) { // no network access + return null; + } + + int count = 1; + final MatcherWrapper matcherViewstateCount = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATEFIELDCOUNT, page); + if (matcherViewstateCount.find()) { + try { + count = Integer.parseInt(matcherViewstateCount.group(1)); + } catch (final NumberFormatException e) { + Log.e("getViewStates", e); + } + } + + final String[] viewstates = new String[count]; + + // Get the viewstates + final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page); + while (matcherViewstates.find()) { + final String sno = matcherViewstates.group(1); // number of viewstate + int no; + if (StringUtils.isEmpty(sno)) { + no = 0; + } else { + try { + no = Integer.parseInt(sno); + } catch (final NumberFormatException e) { + Log.e("getViewStates", e); + no = 0; + } + } + viewstates[no] = matcherViewstates.group(2); + } + + if (viewstates.length != 1 || viewstates[0] != null) { + return viewstates; + } + // no viewstates were present + return null; + } + + /** + * put viewstates into request parameters + */ + public static void putViewstates(final Parameters params, final String[] viewstates) { + if (ArrayUtils.isEmpty(viewstates)) { + return; + } + params.put("__VIEWSTATE", viewstates[0]); + if (viewstates.length > 1) { + for (int i = 1; i < viewstates.length; i++) { + params.put("__VIEWSTATE" + i, viewstates[i]); + } + params.put("__VIEWSTATEFIELDCOUNT", String.valueOf(viewstates.length)); + } + } + + /** + * transfers the viewstates variables from a page (response) to parameters + * (next request) + */ + public static void transferViewstates(final String page, final Parameters params) { + putViewstates(params, getViewstates(page)); + } + + /** + * POST HTTP request. Do the request a second time if the user is not logged in + * + * @param uri + * @return + */ + public static String postRequestLogged(final String uri, final Parameters params) { + final String data = Network.getResponseData(Network.postRequest(uri, params)); + + if (getLoginStatus(data)) { + return data; + } + + if (login() == StatusCode.NO_ERROR) { + return Network.getResponseData(Network.postRequest(uri, params)); + } + + Log.i("Working as guest."); + return data; + } + + /** + * GET HTTP request. Do the request a second time if the user is not logged in + * + * @param uri + * @param params + * @return + */ + @Nullable + public static String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) { + final HttpResponse response = Network.getRequest(uri, params); + final String data = Network.getResponseData(response, canRemoveWhitespace(uri)); + + // A page not found will not be found if the user logs in either + if (Network.isPageNotFound(response) || getLoginStatus(data)) { + return data; + } + + if (login() == StatusCode.NO_ERROR) { + return Network.getResponseData(Network.getRequest(uri, params), canRemoveWhitespace(uri)); + } + + Log.w("Working as guest."); + return data; + } + + /** + * Unfortunately the cache details page contains user generated whitespace in the personal note, therefore we cannot + * remove the white space from cache details pages. + * + * @param uri + * @return + */ + private static boolean canRemoveWhitespace(final String uri) { + return !StringUtils.contains(uri, "cache_details"); + } + + /** Get user session & session token from the Live Map. Needed for following requests */ + public static String[] getMapTokens() { + final HttpResponse response = Network.getRequest(GCConstants.URL_LIVE_MAP); + final String data = Network.getResponseData(response); + final String userSession = TextUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, ""); + final String sessionToken = TextUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, ""); + return new String[] { userSession, sessionToken }; + } +} diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index e2c7dfa..1854024 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -85,7 +85,7 @@ public class GCMap { cache.setDifficulty(Float.parseFloat(difficultyObj.getString("text"))); // 3.5 JSONObject terrainObj = dataObject.getJSONObject("terrain"); cache.setTerrain(Float.parseFloat(terrainObj.getString("text"))); // 1.5 - cache.setHidden(Login.parseGcCustomDate(dataObject.getString("hidden"), "MM/dd/yyyy")); // 7/23/2001 + cache.setHidden(GCLogin.parseGcCustomDate(dataObject.getString("hidden"), "MM/dd/yyyy")); // 7/23/2001 JSONObject containerObj = dataObject.getJSONObject("container"); cache.setSize(CacheSize.getById(containerObj.getString("text"))); // Regular JSONObject typeObj = dataObject.getJSONObject("type"); diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 5b51226..f982582 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -79,7 +79,7 @@ public abstract class GCParser { final SearchResult searchResult = new SearchResult(); searchResult.setUrl(url); - searchResult.viewstates = Login.getViewstates(page); + searchResult.viewstates = GCLogin.getViewstates(page); // recaptcha if (showCaptcha) { @@ -203,7 +203,7 @@ public abstract class GCParser { final String dateHidden = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_HIDDEN_DATE, false, 1, null, false); if (StringUtils.isNotBlank(dateHidden)) { try { - Date date = Login.parseGcCustomDate(dateHidden); + Date date = GCLogin.parseGcCustomDate(dateHidden); if (date != null) { cache.setHidden(date); } @@ -462,13 +462,13 @@ public abstract class GCParser { try { String hiddenString = TextUtils.getMatch(tableInside, GCConstants.PATTERN_HIDDEN, true, null); if (StringUtils.isNotBlank(hiddenString)) { - cache.setHidden(Login.parseGcCustomDate(hiddenString)); + cache.setHidden(GCLogin.parseGcCustomDate(hiddenString)); } if (cache.getHiddenDate() == null) { // event date hiddenString = TextUtils.getMatch(tableInside, GCConstants.PATTERN_HIDDENEVENT, true, null); if (StringUtils.isNotBlank(hiddenString)) { - cache.setHidden(Login.parseGcCustomDate(hiddenString)); + cache.setHidden(GCLogin.parseGcCustomDate(hiddenString)); } } } catch (final ParseException e) { @@ -494,7 +494,7 @@ public abstract class GCParser { try { final String foundDateString = TextUtils.getMatch(page, GCConstants.PATTERN_FOUND_DATE, true, null); if (StringUtils.isNotBlank(foundDateString)) { - cache.setVisitedDate(Login.parseGcCustomDate(foundDateString).getTime()); + cache.setVisitedDate(GCLogin.parseGcCustomDate(foundDateString).getTime()); } } catch (final ParseException e) { // failed to parse cache found date @@ -772,7 +772,7 @@ public abstract class GCParser { return search; } - if (Login.isEmpty(viewstates)) { + if (GCLogin.isEmpty(viewstates)) { Log.e("GCParser.searchByNextPage: No viewstate given"); return search; } @@ -783,10 +783,10 @@ public abstract class GCParser { final Parameters params = new Parameters( "__EVENTTARGET", "ctl00$ContentBody$pgrBottom$ctl08", "__EVENTARGUMENT", ""); - Login.putViewstates(params, viewstates); + GCLogin.putViewstates(params, viewstates); - final String page = Login.postRequestLogged(uri, params); - if (!Login.getLoginStatus(page)) { + final String page = GCLogin.postRequestLogged(uri, params); + if (!GCLogin.getLoginStatus(page)) { Log.e("GCParser.postLogTrackable: Can not log in geocaching"); return search; } @@ -850,7 +850,7 @@ public abstract class GCParser { final String uri = "http://www.geocaching.com/seek/nearest.aspx"; final String fullUri = uri + "?" + addFToParams(params, my, true); - final String page = Login.getRequestLogged(uri, addFToParams(params, my, true)); + final String page = GCLogin.getRequestLogged(uri, addFToParams(params, my, true)); if (StringUtils.isBlank(page)) { Log.e("GCParser.searchByAny: No data from server"); @@ -866,7 +866,7 @@ public abstract class GCParser { final SearchResult search = searchResult.filterSearchResults(Settings.isExcludeDisabledCaches(), false, cacheType); - Login.getLoginStatus(page); + GCLogin.getLoginStatus(page); return search; } @@ -973,7 +973,7 @@ public abstract class GCParser { params.put("id", id); } - final String page = Login.getRequestLogged("http://www.geocaching.com/track/details.aspx", params); + final String page = GCLogin.getRequestLogged("http://www.geocaching.com/track/details.aspx", params); if (StringUtils.isBlank(page)) { Log.e("GCParser.searchTrackable: No data from server"); @@ -994,7 +994,7 @@ public abstract class GCParser { final Parameters params = new Parameters(); - final String page = Login.getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); + final String page = GCLogin.getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); if (StringUtils.isBlank(page)) { Log.e("GCParser.searchPocketQueryList: No data from server"); @@ -1040,7 +1040,7 @@ public abstract class GCParser { public static ImmutablePair postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, final String log, final List trackables) { - if (Login.isEmpty(viewstates)) { + if (GCLogin.isEmpty(viewstates)) { Log.e("GCParser.postLog: No viewstate given"); return new ImmutablePair(StatusCode.LOG_POST_ERROR, ""); } @@ -1061,7 +1061,7 @@ public abstract class GCParser { "__EVENTARGUMENT", "", "__LASTFOCUS", "", "ctl00$ContentBody$LogBookPanel1$ddLogType", Integer.toString(logType.id), - "ctl00$ContentBody$LogBookPanel1$uxDateVisited", Login.getCustomGcDateFormat().format(new GregorianCalendar(year, month - 1, day).getTime()), + "ctl00$ContentBody$LogBookPanel1$uxDateVisited", GCLogin.getCustomGcDateFormat().format(new GregorianCalendar(year, month - 1, day).getTime()), "ctl00$ContentBody$LogBookPanel1$uxDateVisited$Month", Integer.toString(month), "ctl00$ContentBody$LogBookPanel1$uxDateVisited$Day", Integer.toString(day), "ctl00$ContentBody$LogBookPanel1$uxDateVisited$Year", Integer.toString(year), @@ -1074,7 +1074,7 @@ public abstract class GCParser { "ctl00$ContentBody$LogBookPanel1$btnSubmitLog", "Submit Log Entry", "ctl00$ContentBody$LogBookPanel1$uxLogCreationSource", "Old", "ctl00$ContentBody$uxVistOtherListingGC", ""); - Login.putViewstates(params, viewstates); + GCLogin.putViewstates(params, viewstates); if (trackables != null && !trackables.isEmpty()) { // we have some trackables to proceed final StringBuilder hdnSelected = new StringBuilder(); @@ -1091,8 +1091,8 @@ public abstract class GCParser { } final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/log.aspx").encodedQuery("ID=" + cacheid).build().toString(); - String page = Login.postRequestLogged(uri, params); - if (!Login.getLoginStatus(page)) { + String page = GCLogin.postRequestLogged(uri, params); + if (!GCLogin.getLoginStatus(page)) { Log.e("GCParser.postLog: Cannot log in geocaching"); return new ImmutablePair(StatusCode.NOT_LOGGED_IN, ""); } @@ -1103,15 +1103,15 @@ public abstract class GCParser { try { if (matcher.find() && matcher.groupCount() > 0) { - final String[] viewstatesConfirm = Login.getViewstates(page); + final String[] viewstatesConfirm = GCLogin.getViewstates(page); - if (Login.isEmpty(viewstatesConfirm)) { + if (GCLogin.isEmpty(viewstatesConfirm)) { Log.e("GCParser.postLog: No viewstate for confirm log"); return new ImmutablePair(StatusCode.LOG_POST_ERROR, ""); } params.clear(); - Login.putViewstates(params, viewstatesConfirm); + GCLogin.putViewstates(params, viewstatesConfirm); params.put("__EVENTTARGET", ""); params.put("__EVENTARGUMENT", ""); params.put("__LASTFOCUS", ""); @@ -1156,10 +1156,10 @@ public abstract class GCParser { DataStore.saveVisitDate(geocode); } - Login.getLoginStatus(page); + GCLogin.getLoginStatus(page); // the log-successful-page contains still the old value - if (Login.getActualCachesFound() >= 0) { - Login.setActualCachesFound(Login.getActualCachesFound() + 1); + if (GCLogin.getActualCachesFound() >= 0) { + GCLogin.setActualCachesFound(GCLogin.getActualCachesFound() + 1); } final String logID = TextUtils.getMatch(page, GCConstants.PATTERN_LOG_IMAGE_UPLOAD, ""); @@ -1190,14 +1190,14 @@ public abstract class GCParser { public static ImmutablePair uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) { final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").encodedQuery("LID=" + logId).build().toString(); - final String page = Login.getRequestLogged(uri, null); + final String page = GCLogin.getRequestLogged(uri, null); if (StringUtils.isBlank(page)) { Log.e("GCParser.uploadLogImage: No data from server"); return new ImmutablePair(StatusCode.UNKNOWN_ERROR, null); } assert page != null; - final String[] viewstates = Login.getViewstates(page); + final String[] viewstates = GCLogin.getViewstates(page); final Parameters uploadParams = new Parameters( "__EVENTTARGET", "", @@ -1205,7 +1205,7 @@ public abstract class GCParser { "ctl00$ContentBody$ImageUploadControl1$uxFileCaption", caption, "ctl00$ContentBody$ImageUploadControl1$uxFileDesc", description, "ctl00$ContentBody$ImageUploadControl1$uxUpload", "Upload"); - Login.putViewstates(uploadParams, viewstates); + GCLogin.putViewstates(uploadParams, viewstates); final File image = new File(imageUri.getPath()); final String response = Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$ImageUploadControl1$uxFileUpload", "image/jpeg", image)); @@ -1229,7 +1229,7 @@ public abstract class GCParser { */ public static StatusCode postLogTrackable(final String tbid, final String trackingCode, final String[] viewstates, final LogType logType, final int year, final int month, final int day, final String log) { - if (Login.isEmpty(viewstates)) { + if (GCLogin.isEmpty(viewstates)) { Log.e("GCParser.postLogTrackable: No viewstate given"); return StatusCode.LOG_POST_ERROR; } @@ -1250,13 +1250,13 @@ public abstract class GCParser { "__LASTFOCUS", "", "ctl00$ContentBody$LogBookPanel1$ddLogType", Integer.toString(logType.id), "ctl00$ContentBody$LogBookPanel1$tbCode", trackingCode); - Login.putViewstates(params, viewstates); + GCLogin.putViewstates(params, viewstates); if (currentDate.get(Calendar.YEAR) == year && (currentDate.get(Calendar.MONTH) + 1) == month && currentDate.get(Calendar.DATE) == day) { params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged", ""); params.put("ctl00$ContentBody$LogBookPanel1$uxDateVisited", ""); } else { params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged", Integer.toString(month) + "/" + Integer.toString(day) + "/" + Integer.toString(year)); - params.put("ctl00$ContentBody$LogBookPanel1$uxDateVisited", Login.getCustomGcDateFormat().format(new GregorianCalendar(year, month - 1, day).getTime())); + params.put("ctl00$ContentBody$LogBookPanel1$uxDateVisited", GCLogin.getCustomGcDateFormat().format(new GregorianCalendar(year, month - 1, day).getTime())); } params.put( "ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Day", Integer.toString(day), @@ -1272,8 +1272,8 @@ public abstract class GCParser { "ctl00$ContentBody$uxVistOtherListingGC", ""); final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/track/log.aspx").encodedQuery("wid=" + tbid).build().toString(); - final String page = Login.postRequestLogged(uri, params); - if (!Login.getLoginStatus(page)) { + final String page = GCLogin.postRequestLogged(uri, params); + if (!GCLogin.getLoginStatus(page)) { Log.e("GCParser.postLogTrackable: Cannot log in geocaching"); return StatusCode.NOT_LOGGED_IN; } @@ -1302,7 +1302,7 @@ public abstract class GCParser { */ static boolean addToWatchlist(final Geocache cache) { final String uri = "http://www.geocaching.com/my/watchlist.aspx?w=" + cache.getCacheId(); - final String page = Login.postRequestLogged(uri, null); + final String page = GCLogin.postRequestLogged(uri, null); if (StringUtils.isBlank(page)) { Log.e("GCParser.addToWatchlist: No data from server"); @@ -1328,7 +1328,7 @@ public abstract class GCParser { */ static boolean removeFromWatchlist(final Geocache cache) { final String uri = "http://www.geocaching.com/my/watchlist.aspx?ds=1&action=rem&id=" + cache.getCacheId(); - String page = Login.postRequestLogged(uri, null); + String page = GCLogin.postRequestLogged(uri, null); if (StringUtils.isBlank(page)) { Log.e("GCParser.removeFromWatchlist: No data from server"); @@ -1340,7 +1340,7 @@ public abstract class GCParser { "__EVENTTARGET", "", "__EVENTARGUMENT", "", "ctl00$ContentBody$btnYes", "Yes"); - Login.transferViewstates(page, params); + GCLogin.transferViewstates(page, params); page = Network.getResponseData(Network.postRequest(uri, params)); final boolean guidOnPage = cache.isGuidContainedInPage(page); @@ -1364,7 +1364,7 @@ public abstract class GCParser { params.put("log", log); params.put("numlogs", numlogs); - return Login.getRequestLogged("http://www.geocaching.com/seek/cache_details.aspx", params); + return GCLogin.getRequestLogged("http://www.geocaching.com/seek/cache_details.aspx", params); } /** @@ -1560,7 +1560,7 @@ public abstract class GCParser { while (matcherLogs.find()) { long date = 0; try { - date = Login.parseGcCustomDate(matcherLogs.group(2)).getTime(); + date = GCLogin.parseGcCustomDate(matcherLogs.group(2)).getTime(); } catch (final ParseException e) { } @@ -1691,7 +1691,7 @@ public abstract class GCParser { long date = 0; try { - date = Login.parseGcCustomDate(entry.getString("Visited")).getTime(); + date = GCLogin.parseGcCustomDate(entry.getString("Visited")).getTime(); } catch (final ParseException e) { Log.e("GCParser.loadLogsFromDetails: failed to parse log date."); } diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java deleted file mode 100644 index beb49f1..0000000 --- a/main/src/cgeo/geocaching/connector/gc/Login.java +++ /dev/null @@ -1,517 +0,0 @@ -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 org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; - -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 = "English▼"; - - // 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 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 map = new HashMap(); - - 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 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() + ')'); - - Login.switchToEnglish(loginData); - Settings.setCookieStore(Cookies.dumpCookieStore()); - - return StatusCode.NO_ERROR; // logged in - } - - if (loginData.contains("Your username/password combination does not match.")) { - Log.i("Failed to log in Geocaching.com as " + login.left + " because of wrong username/password"); - return StatusCode.WRONG_LOGIN_DATA; // wrong login - } - - if (loginData.contains("You must validate your account before you can log in.")) { - Log.i("Failed to log in Geocaching.com as " + login.left + " because account needs to be validated first"); - return StatusCode.UNVALIDATED_ACCOUNT; - } - - Log.i("Failed to log in Geocaching.com as " + login.left + " for some unknown reason"); - if (retry) { - Login.switchToEnglish(loginData); - return login(false); - } - - return StatusCode.UNKNOWN_ERROR; // can't login - } - - public static StatusCode logout() { - final HttpResponse logoutResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f"); - final String logoutData = Network.getResponseData(logoutResponse); - if (logoutResponse != null && logoutResponse.getStatusLine().getStatusCode() == 503 && TextUtils.matches(logoutData, GCConstants.PATTERN_MAINTENANCE)) { - return StatusCode.MAINTENANCE; - } - - resetLoginStatus(); - - return StatusCode.NO_ERROR; - } - - private static void resetLoginStatus() { - Cookies.clearCookies(); - Settings.setCookieStore(null); - - setActualLoginStatus(false); - } - - private static void clearLoginInfo() { - resetLoginStatus(); - - setActualCachesFound(-1); - setActualStatus(CgeoApplication.getInstance().getString(R.string.err_login)); - } - - static void setActualCachesFound(final int found) { - actualCachesFound = found; - } - - public static String getActualStatus() { - return actualStatus; - } - - private static void setActualStatus(final String status) { - actualStatus = status; - } - - public static boolean isActualLoginStatus() { - return actualLoginStatus; - } - - private static void setActualLoginStatus(boolean loginStatus) { - actualLoginStatus = loginStatus; - } - - public static String getActualUserName() { - return actualUserName; - } - - private static void setActualUserName(String userName) { - actualUserName = userName; - } - - public static int getActualCachesFound() { - return actualCachesFound; - } - - /** - * Check if the user has been logged in when he retrieved the data. - * - * @param page - * @return true if user is logged in, false otherwise - */ - public static boolean getLoginStatus(@Nullable final String page) { - if (StringUtils.isBlank(page)) { - Log.e("Login.checkLogin: No page given"); - return false; - } - assert page != null; - - setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_ok)); - - // on every page except login page - setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME)); - if (isActualLoginStatus()) { - setActualUserName(TextUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); - int cachesCount = 0; - try { - cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); - } catch (final NumberFormatException e) { - Log.e("getLoginStatus: bad cache count", e); - } - setActualCachesFound(cachesCount); - Settings.setMemberStatus(TextUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, null)); - if ( page.contains(GCConstants.MEMBER_STATUS_RENEW) ) { - Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM); - } - return true; - } - - // login page - setActualLoginStatus(TextUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE)); - if (isActualLoginStatus()) { - setActualUserName(Settings.getUsername()); - // number of caches found is not part of this page - return true; - } - - setActualStatus(CgeoApplication.getInstance().getString(R.string.init_login_popup_failed)); - return false; - } - - private static void switchToEnglish(String previousPage) { - if (previousPage != null && previousPage.contains(ENGLISH)) { - Log.i("Geocaching.com language already set to English"); - // get find count - getLoginStatus(Network.getResponseData(Network.getRequest("http://www.geocaching.com/email/"))); - } else { - final String page = Network.getResponseData(Network.getRequest(LANGUAGE_CHANGE_URI)); - getLoginStatus(page); - if (page == null) { - Log.e("Failed to read viewstates to set geocaching.com language"); - } - final Parameters params = new Parameters( - "__EVENTTARGET", "ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem", // switch to english - "__EVENTARGUMENT", ""); - Login.transferViewstates(page, params); - final HttpResponse response = Network.postRequest(LANGUAGE_CHANGE_URI, params, new Parameters("Referer", LANGUAGE_CHANGE_URI)); - if (Network.isSuccess(response)) { - Log.i("changed language on geocaching.com to English"); - } else { - Log.e("Failed to set geocaching.com language to English"); - } - } - } - - public static BitmapDrawable downloadAvatarAndGetMemberStatus() { - try { - final String responseData = StringUtils.defaultString(Network.getResponseData(Network.getRequest("http://www.geocaching.com/my/"))); - final String profile = TextUtils.replaceWhitespace(responseData); - - Settings.setMemberStatus(TextUtils.getMatch(profile, GCConstants.PATTERN_MEMBER_STATUS, true, null)); - if (profile.contains(GCConstants.MEMBER_STATUS_RENEW)) { - Settings.setMemberStatus(GCConstants.MEMBER_STATUS_PM); - } - - setActualCachesFound(Integer.parseInt(TextUtils.getMatch(profile, GCConstants.PATTERN_CACHES_FOUND, true, "-1").replaceAll("[,.]", ""))); - - final String avatarURL = TextUtils.getMatch(profile, GCConstants.PATTERN_AVATAR_IMAGE_PROFILE_PAGE, false, null); - if (null != avatarURL) { - final HtmlImage imgGetter = new HtmlImage("", false, 0, false); - return imgGetter.getDrawable(avatarURL); - } - // No match? There may be no avatar set by user. - Log.d("No avatar set for user"); - } catch (final Exception e) { - Log.w("Error when retrieving user avatar", e); - } - return null; - } - - /** - * Detect user date settings on geocaching.com - */ - public static void detectGcCustomDate() { - - final String result = Network.getResponseData(Network.getRequest("http://www.geocaching.com/account/ManagePreferences.aspx")); - - if (null == result) { - Log.w("Login.detectGcCustomDate: result is null"); - return; - } - - final String customDate = TextUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null); - if (null != customDate) { - Settings.setGcCustomDate(customDate); - } - } - - public static Date parseGcCustomDate(final String input, final String format) throws ParseException { - if (StringUtils.isBlank(input)) { - throw new ParseException("Input is null", 0); - } - - final String trimmed = input.trim(); - - if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) { - try { - return GC_CUSTOM_DATE_FORMATS.get(format).parse(trimmed); - } catch (final ParseException e) { - } - } - - for (final SimpleDateFormat sdf : GC_CUSTOM_DATE_FORMATS.values()) { - try { - return sdf.parse(trimmed); - } catch (final ParseException e) { - } - } - - throw new ParseException("No matching pattern", 0); - } - - public static Date parseGcCustomDate(final String input) throws ParseException { - return parseGcCustomDate(input, Settings.getGcCustomDate()); - } - - public static SimpleDateFormat getCustomGcDateFormat() { - final String format = Settings.getGcCustomDate(); - if (GC_CUSTOM_DATE_FORMATS.containsKey(format)) { - return GC_CUSTOM_DATE_FORMATS.get(format); - } - - return GC_CUSTOM_DATE_FORMATS.get(DEFAULT_CUSTOM_DATE_FORMAT); - } - - /** - * checks if an Array of Strings is empty or not. Empty means: - * - Array is null - * - or all elements are null or empty strings - */ - public static boolean isEmpty(String[] a) { - if (a == null) { - return true; - } - - for (final String s : a) { - if (StringUtils.isNotEmpty(s)) { - return false; - } - } - return true; - } - - /** - * read all viewstates from page - * - * @return String[] with all view states - */ - public static String[] getViewstates(String page) { - // Get the number of viewstates. - // If there is only one viewstate, __VIEWSTATEFIELDCOUNT is not present - - if (page == null) { // no network access - return null; - } - - int count = 1; - final MatcherWrapper matcherViewstateCount = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATEFIELDCOUNT, page); - if (matcherViewstateCount.find()) { - try { - count = Integer.parseInt(matcherViewstateCount.group(1)); - } catch (final NumberFormatException e) { - Log.e("getViewStates", e); - } - } - - final String[] viewstates = new String[count]; - - // Get the viewstates - final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page); - while (matcherViewstates.find()) { - final String sno = matcherViewstates.group(1); // number of viewstate - int no; - if (StringUtils.isEmpty(sno)) { - no = 0; - } else { - try { - no = Integer.parseInt(sno); - } catch (final NumberFormatException e) { - Log.e("getViewStates", e); - no = 0; - } - } - viewstates[no] = matcherViewstates.group(2); - } - - if (viewstates.length != 1 || viewstates[0] != null) { - return viewstates; - } - // no viewstates were present - return null; - } - - /** - * put viewstates into request parameters - */ - public static void putViewstates(final Parameters params, final String[] viewstates) { - if (ArrayUtils.isEmpty(viewstates)) { - return; - } - params.put("__VIEWSTATE", viewstates[0]); - if (viewstates.length > 1) { - for (int i = 1; i < viewstates.length; i++) { - params.put("__VIEWSTATE" + i, viewstates[i]); - } - params.put("__VIEWSTATEFIELDCOUNT", String.valueOf(viewstates.length)); - } - } - - /** - * transfers the viewstates variables from a page (response) to parameters - * (next request) - */ - public static void transferViewstates(final String page, final Parameters params) { - putViewstates(params, getViewstates(page)); - } - - /** - * POST HTTP request. Do the request a second time if the user is not logged in - * - * @param uri - * @return - */ - public static String postRequestLogged(final String uri, final Parameters params) { - final String data = Network.getResponseData(Network.postRequest(uri, params)); - - if (getLoginStatus(data)) { - return data; - } - - if (login() == StatusCode.NO_ERROR) { - return Network.getResponseData(Network.postRequest(uri, params)); - } - - Log.i("Working as guest."); - return data; - } - - /** - * GET HTTP request. Do the request a second time if the user is not logged in - * - * @param uri - * @param params - * @return - */ - @Nullable - public static String getRequestLogged(@NonNull final String uri, @Nullable final Parameters params) { - final HttpResponse response = Network.getRequest(uri, params); - final String data = Network.getResponseData(response, canRemoveWhitespace(uri)); - - // A page not found will not be found if the user logs in either - if (Network.isPageNotFound(response) || getLoginStatus(data)) { - return data; - } - - if (login() == StatusCode.NO_ERROR) { - return Network.getResponseData(Network.getRequest(uri, params), canRemoveWhitespace(uri)); - } - - Log.w("Working as guest."); - return data; - } - - /** - * Unfortunately the cache details page contains user generated whitespace in the personal note, therefore we cannot - * remove the white space from cache details pages. - * - * @param uri - * @return - */ - private static boolean canRemoveWhitespace(final String uri) { - return !StringUtils.contains(uri, "cache_details"); - } - - /** Get user session & session token from the Live Map. Needed for following requests */ - public static String[] getMapTokens() { - final HttpResponse response = Network.getRequest(GCConstants.URL_LIVE_MAP); - final String data = Network.getResponseData(response); - final String userSession = TextUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, ""); - final String sessionToken = TextUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, ""); - return new String[] { userSession, sessionToken }; - } -} diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java index 1ae97f3..f52a192 100644 --- a/main/src/cgeo/geocaching/export/FieldnoteExport.java +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -5,7 +5,7 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; @@ -175,30 +175,30 @@ class FieldnoteExport extends AbstractExport { if (upload) { publishProgress(STATUS_UPLOAD); - if (!Login.isActualLoginStatus()) { + if (!GCLogin.isActualLoginStatus()) { // no need to upload (possibly large file) if we're not logged in - final StatusCode loginState = Login.login(); + final StatusCode loginState = GCLogin.login(); if (loginState != StatusCode.NO_ERROR) { Log.e("FieldnoteExport.ExportTask upload: Login failed"); } } final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx"; - final String page = Login.getRequestLogged(uri, null); + final String page = GCLogin.getRequestLogged(uri, null); if (StringUtils.isBlank(page)) { Log.e("FieldnoteExport.ExportTask get page: No data from server"); return false; } - final String[] viewstates = Login.getViewstates(page); + final String[] viewstates = GCLogin.getViewstates(page); final Parameters uploadParams = new Parameters( "__EVENTTARGET", "", "__EVENTARGUMENT", "", "ctl00$ContentBody$btnUpload", "Upload Field Note"); - Login.putViewstates(uploadParams, viewstates); + GCLogin.putViewstates(uploadParams, viewstates); Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$FieldNoteLoader", "text/plain", exportFile)); diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 08efd17..d331a73 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -11,7 +11,7 @@ import cgeo.geocaching.SearchResult; import cgeo.geocaching.Waypoint; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.connector.gc.Tile; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; @@ -1171,7 +1171,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto do { if (tokens == null) { - tokens = Login.getMapTokens(); + tokens = GCLogin.getMapTokens(); if (noMapTokenHandler != null && tokens == null) { noMapTokenHandler.sendEmptyMessage(0); } @@ -1180,7 +1180,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens); downloaded = true; if (searchResult.getError() == StatusCode.NOT_LOGGED_IN && Settings.isGCConnectorActive()) { - Login.login(); + GCLogin.login(); tokens = null; } else { break; diff --git a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java index 434f7d7..566ed7c 100644 --- a/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java +++ b/main/src/cgeo/geocaching/settings/CheckGcCredentialsPreference.java @@ -1,6 +1,6 @@ package cgeo.geocaching.settings; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.StatusCode; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -29,11 +29,11 @@ public class CheckGcCredentialsPreference extends AbstractCheckCredentialsPrefer @Override protected Object login() { - final StatusCode loginResult = Login.login(); + final StatusCode loginResult = GCLogin.login(); Object payload = loginResult; if (loginResult == StatusCode.NO_ERROR) { - Login.detectGcCustomDate(); - payload = Login.downloadAvatarAndGetMemberStatus(); + GCLogin.detectGcCustomDate(); + payload = GCLogin.downloadAvatarAndGetMemberStatus(); } return payload; } diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index 88d4344..176e07d 100644 --- a/main/src/cgeo/geocaching/settings/Settings.java +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -4,7 +4,7 @@ import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.R; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; import cgeo.geocaching.connector.gc.GCConstants; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy; import cgeo.geocaching.enumerations.LogType; @@ -489,7 +489,7 @@ public class Settings { /** * @return User selected date format on GC.com - * @see Login#GC_CUSTOM_DATE_FORMATS + * @see GCLogin#GC_CUSTOM_DATE_FORMATS */ public static String getGcCustomDate() { return getString(R.string.pref_gccustomdate, null); diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java index c25e796..f9c23b3 100644 --- a/main/src/cgeo/geocaching/settings/SettingsActivity.java +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -9,7 +9,7 @@ import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum; import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.gc.GCConnector; -import cgeo.geocaching.connector.gc.Login; +import cgeo.geocaching.connector.gc.GCLogin; import cgeo.geocaching.files.SimpleDirChooser; import cgeo.geocaching.maps.MapProviderFactory; import cgeo.geocaching.maps.interfaces.MapSource; @@ -528,8 +528,8 @@ public class SettingsActivity extends PreferenceActivity { } if ((isPreference(preference, R.string.pref_username) && !stringValue.equals(Settings.getUsername())) || (isPreference(preference, R.string.pref_password) && !stringValue.equals(Settings.getGcLogin().getRight()))) { // reset log-in if gc user or password is changed - if (Login.isActualLoginStatus()) { - Login.logout(); + if (GCLogin.isActualLoginStatus()) { + GCLogin.logout(); } CgeoApplication.getInstance().checkLogin = true; } -- cgit v1.1