diff options
Diffstat (limited to 'main/src/cgeo/geocaching/connector')
22 files changed, 481 insertions, 271 deletions
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 83c1b6f..28ad12b 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -31,30 +31,22 @@ public abstract class AbstractConnector implements IConnector { } @Override - public boolean supportsOwnCoordinates() { + public boolean supportsPersonalNote() { return false; } - /** - * Uploading modified coordinates to website - * - * @param cache - * @param wpt - * @return success - */ @Override - public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) { + public boolean uploadPersonalNote(Geocache cache) { throw new UnsupportedOperationException(); } - /** - * Uploading personal note to website - * - * @param cache - * @return success - */ @Override - public boolean uploadPersonalNote(Geocache cache) { + public boolean supportsOwnCoordinates() { + return false; + } + + @Override + public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) { throw new UnsupportedOperationException(); } @@ -122,11 +114,6 @@ public abstract class AbstractConnector implements IConnector { } @Override - public String[] getTokens() { - return null; - } - - @Override public String getGeocodeFromUrl(final String url) { final String urlPrefix = getCacheUrlPrefix(); if (StringUtils.startsWith(url, urlPrefix)) { diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index 1849e4b..eb09978 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -4,6 +4,7 @@ import cgeo.geocaching.ICache; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Trackable; +import cgeo.geocaching.connector.capability.ILogin; import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.connector.gc.GCConnector; @@ -25,9 +26,9 @@ import java.util.List; public final class ConnectorFactory { private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector(); - private static final IConnector[] connectors = new IConnector[] { + private static final IConnector[] CONNECTORS = new IConnector[] { GCConnector.getInstance(), - new OCApiLiveConnector("Opencaching.de", "www.opencaching.de", "OC", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, ApiSupport.current), + new OCApiLiveConnector("opencaching.de", "www.opencaching.de", "OC", R.string.oc_de_okapi_consumer_key, R.string.oc_de_okapi_consumer_secret, ApiSupport.current), new OCConnector("OpenCaching.CZ", "www.opencaching.cz", "OZ"), new OCApiConnector("OpenCaching.CO.UK", "www.opencaching.org.uk", "OK", "arU4okouc4GEjMniE2fq", ApiSupport.oldapi), new OCConnector("OpenCaching.ES", "www.opencachingspain.es", "OC"), @@ -46,8 +47,8 @@ public final class ConnectorFactory { public static final UnknownTrackableConnector UNKNOWN_TRACKABLE_CONNECTOR = new UnknownTrackableConnector(); private static final TrackableConnector[] TRACKABLE_CONNECTORS = new TrackableConnector[] { - new TravelBugConnector(), - new GeokretyConnector(), + new GeokretyConnector(), // GK must be first, as it overlaps with the secret codes of travel bugs + TravelBugConnector.getInstance(), UNKNOWN_TRACKABLE_CONNECTOR // must be last }; @@ -57,7 +58,7 @@ public final class ConnectorFactory { static { final List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>(); - for (final IConnector conn : connectors) { + for (final IConnector conn : CONNECTORS) { if (conn instanceof ISearchByViewPort) { vpConns.add((ISearchByViewPort) conn); } @@ -65,7 +66,7 @@ public final class ConnectorFactory { searchByViewPortConns = vpConns.toArray(new ISearchByViewPort[vpConns.size()]); final List<ISearchByCenter> centerConns = new ArrayList<ISearchByCenter>(); - for (final IConnector conn : connectors) { + for (final IConnector conn : CONNECTORS) { // GCConnector is handled specially, omit it here! if (conn instanceof ISearchByCenter && !(conn instanceof GCConnector)) { centerConns.add((ISearchByCenter) conn); @@ -75,18 +76,28 @@ public final class ConnectorFactory { } public static IConnector[] getConnectors() { - return connectors; + return CONNECTORS; } public static ISearchByCenter[] getSearchByCenterConnectors() { return searchByCenterConns; } + public static ILogin[] getActiveLiveConnectors() { + final List<ILogin> liveConns = new ArrayList<ILogin>(); + for (final IConnector conn : CONNECTORS) { + if (conn instanceof ILogin && conn.isActivated()) { + liveConns.add((ILogin) conn); + } + } + return liveConns.toArray(new ILogin[liveConns.size()]); + } + public static boolean canHandle(final String geocode) { if (isInvalidGeocode(geocode)) { return false; } - for (final IConnector connector : connectors) { + for (final IConnector connector : CONNECTORS) { if (connector.canHandle(geocode)) { return true; } @@ -117,7 +128,7 @@ public final class ConnectorFactory { if (isInvalidGeocode(geocode)) { return UNKNOWN_CONNECTOR; } - for (final IConnector connector : connectors) { + for (final IConnector connector : CONNECTORS) { if (connector.canHandle(geocode)) { return connector; } @@ -136,17 +147,14 @@ public final class ConnectorFactory { final SearchResult result = new SearchResult(); for (final ISearchByViewPort vpconn : searchByViewPortConns) { if (vpconn.isActivated()) { - final SearchResult temp = vpconn.searchByViewport(viewport, tokens); - if (temp != null) { - result.addGeocodes(temp.getGeocodes()); - } + result.addSearchResult(vpconn.searchByViewport(viewport, tokens)); } } return result; } public static String getGeocodeFromURL(final String url) { - for (final IConnector connector : connectors) { + for (final IConnector connector : CONNECTORS) { final String geocode = connector.getGeocodeFromUrl(url); if (StringUtils.isNotBlank(geocode)) { return geocode; @@ -155,4 +163,8 @@ public final class ConnectorFactory { return null; } + public static TrackableConnector[] getTrackableConnectors() { + return TRACKABLE_CONNECTORS; + } + } diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index c44b946..0c175cd 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -129,13 +129,6 @@ public interface IConnector { public boolean isReliableLatLon(boolean cacheHasReliableLatLon); /** - * Return required tokens for specific following actions - * - * @return - */ - public String[] getTokens(); - - /** * extract a geocode from the given URL, if this connector can handle that URL somehow * * @param url @@ -144,11 +137,11 @@ public interface IConnector { public String getGeocodeFromUrl(final String url); /** - * enable/disable uploading modified coordinates to website + * enable/disable uploading personal note * * @return true, when uploading is possible */ - public boolean supportsOwnCoordinates(); + public boolean supportsPersonalNote(); /** * Uploading personal note to website @@ -159,7 +152,14 @@ public interface IConnector { public boolean uploadPersonalNote(Geocache cache); /** - * Reseting of modified coordinates on website to details + * enable/disable uploading modified coordinates to website + * + * @return true, when uploading is possible + */ + public boolean supportsOwnCoordinates(); + + /** + * Resetting of modified coordinates on website to details * * @param cache * @return success diff --git a/main/src/cgeo/geocaching/connector/ILoggingManager.java b/main/src/cgeo/geocaching/connector/ILoggingManager.java index f0029f9..c5586b3 100644 --- a/main/src/cgeo/geocaching/connector/ILoggingManager.java +++ b/main/src/cgeo/geocaching/connector/ILoggingManager.java @@ -11,10 +11,23 @@ import java.util.List; public interface ILoggingManager { + /** + * Post a log for a cache online + * + * @param cache + * @param logType + * @param date + * @param log + * @param logPassword + * optional, maybe null + * @param trackableLogs + * @return + */ LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, + String logPassword, List<TrackableLog> trackableLogs); ImageResult postLogImage(String logId, diff --git a/main/src/cgeo/geocaching/connector/NoLoggingManager.java b/main/src/cgeo/geocaching/connector/NoLoggingManager.java index bfea4ca..04a73c1 100644 --- a/main/src/cgeo/geocaching/connector/NoLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/NoLoggingManager.java @@ -19,7 +19,7 @@ public class NoLoggingManager implements ILoggingManager { } @Override - public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) { + public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) { return new LogResult(StatusCode.LOG_POST_ERROR, ""); } diff --git a/main/src/cgeo/geocaching/connector/capability/ILogin.java b/main/src/cgeo/geocaching/connector/capability/ILogin.java new file mode 100644 index 0000000..4a839c8 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/capability/ILogin.java @@ -0,0 +1,57 @@ +package cgeo.geocaching.connector.capability; + +import cgeo.geocaching.connector.IConnector; + +import android.content.Context; +import android.os.Handler; + +public interface ILogin extends IConnector { + + + /** + * Contacts the server the connector belongs to + * and verifies/establishes authentication and + * retrieves information about the current user + * (Name, found caches) if applicable. + * + * @param handler + * Handler to receive status feedback + * @param fromActivity + * Calling activity context + * @return true in case of success, false in case of failure + */ + boolean login(Handler handler, Context fromActivity); + + /** + * Returns the status of the last {@link}login() request + * + * @return + */ + boolean isLoggedIn(); + + /** + * User-centered string describing the current login/connection status + * + * @return + */ + String getLoginStatusString(); + + /** + * Name the user has in this connector or empty string if not applicable + * It might be necessary to execute login before this information is valid. + * + * @return + */ + String getUserName(); + + /** + * Number of caches the user has found in this connector + * Normally retrieved/updated with (@see login). + * Might be out dated as changes on the connectors site + * are generally not notified. + * + * @return + */ + int getCachesFound(); + +} diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index fab4332..e6fff79 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -4,16 +4,19 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.ICache; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; import cgeo.geocaching.cgData; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.connector.ILoggingManager; +import cgeo.geocaching.connector.capability.ILogin; import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.capability.ISearchByGeocode; import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.settings.SettingsActivity; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; @@ -21,10 +24,12 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.app.Activity; +import android.content.Context; +import android.os.Handler; import java.util.regex.Pattern; -public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort { +public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ILogin { private static final String CACHE_URL_SHORT = "http://coord.info/"; // Double slash is used to force open in browser @@ -33,7 +38,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, * Pocket queries downloaded from the website use a numeric prefix. The pocket query creator Android app adds a * verbatim "pocketquery" prefix. */ - private static final Pattern gpxZipFilePattern = Pattern.compile("((\\d{7,})|(pocketquery))" + "(_.+)?" + "\\.zip", Pattern.CASE_INSENSITIVE); + private static final Pattern GPX_ZIP_FILE_PATTERN = Pattern.compile("((\\d{7,})|(pocketquery))" + "(_.+)?" + "\\.zip", Pattern.CASE_INSENSITIVE); /** * Pattern for GC codes @@ -74,6 +79,11 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override + public boolean supportsPersonalNote() { + return true; + } + + @Override public boolean supportsOwnCoordinates() { return true; } @@ -105,7 +115,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, @Override public String getName() { - return "GeoCaching.com"; + return "geocaching.com"; } @Override @@ -161,7 +171,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, @Override public boolean isZippedGPXFile(final String fileName) { - return gpxZipFilePattern.matcher(fileName).matches(); + return GPX_ZIP_FILE_PATTERN.matcher(fileName).matches(); } @Override @@ -282,4 +292,46 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } return R.drawable.marker; } + + @Override + public boolean login(Handler handler, Context fromActivity) { + // login + final StatusCode status = Login.login(); + + if (status == StatusCode.NO_ERROR) { + cgeoapplication.getInstance().firstRun = false; + Login.detectGcCustomDate(); + } + + if (cgeoapplication.getInstance().showLoginToast && handler != null) { + handler.sendMessage(handler.obtainMessage(0, status)); + cgeoapplication.getInstance().showLoginToast = false; + + // invoke settings activity to insert login details + if (status == StatusCode.NO_LOGIN_INFO_STORED && fromActivity != null) { + SettingsActivity.jumpToServicesPage(fromActivity); + } + } + return status == StatusCode.NO_ERROR; + } + + @Override + public String getUserName() { + return Login.getActualUserName(); + } + + @Override + public int getCachesFound() { + return Login.getActualCachesFound(); + } + + @Override + public String getLoginStatusString() { + return Login.getActualStatus(); + } + + @Override + public boolean isLoggedIn() { + return Login.isActualLoginStatus(); + } } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java index f2e2e69..c2aeffd 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java @@ -36,7 +36,7 @@ public final class GCConstants { public final static Pattern PATTERN_LATLON = Pattern.compile("<span id=\"uxLatLon\"[^>]*>(.*?)</span>"); public final static Pattern PATTERN_LATLON_ORIG = Pattern.compile("\\{\"isUserDefined\":true[^}]+?\"oldLatLngDisplay\":\"([^\"]+)\"\\}"); public final static Pattern PATTERN_LOCATION = Pattern.compile(Pattern.quote("<span id=\"ctl00_ContentBody_Location\">In ") + "(?:<a href=[^>]*>)?(.*?)<"); - public final static Pattern PATTERN_PERSONALNOTE = Pattern.compile("<p id=\"cache_note\"[^>]*>(.*?)</p>"); + public final static Pattern PATTERN_PERSONALNOTE = Pattern.compile("<p id=\"cache_note\"[^>]*>(.*?)</p>", Pattern.DOTALL); public final static Pattern PATTERN_NAME = Pattern.compile("<span id=\"ctl00_ContentBody_CacheName\">(.*?)</span>"); public final static Pattern PATTERN_DIFFICULTY = Pattern.compile("<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\""); public final static Pattern PATTERN_TERRAIN = Pattern.compile("<span id=\"ctl00_ContentBody_Localize[\\d]+\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\""); @@ -69,7 +69,7 @@ public final class GCConstants { public static final String MEMBER_STATUS_RENEW = "<a id=\"ctl00_hlRenew"; public static final String MEMBER_STATUS_PM = "Premium Member"; /** Use replaceAll("[,.]","") on the resulting string before converting to an int */ - public static final Pattern PATTERN_CACHES_FOUND = Pattern.compile("<strong[^>]*>.*?([\\d,.]+) Caches Found"); + public static final Pattern PATTERN_CACHES_FOUND = Pattern.compile("<strong[^>]*>.*?([\\d,.]+) Caches Found", Pattern.DOTALL); public static final Pattern PATTERN_AVATAR_IMAGE_PROFILE_PAGE = Pattern.compile("<img src=\"(http://img.geocaching.com/user/avatar/[0-9a-f-]+\\.jpg)\"[^>]*\\salt=\"Avatar\""); public static final Pattern PATTERN_LOGIN_NAME_LOGIN_PAGE = Pattern.compile("ctl00_ContentBody_lbUsername\">.*<strong>(.*)</strong>"); public static final Pattern PATTERN_CUSTOMDATE = Pattern.compile("<option selected=\"selected\" value=\"([ /Mdy-]+)\">"); @@ -122,11 +122,12 @@ public final class GCConstants { public final static Pattern PATTERN_SEARCH_DIFFICULTY_TERRAIN = Pattern.compile("<span class=\"small\">([0-5]([\\.,]5)?)/([0-5]([\\.,]5)?)</span><br />"); public final static Pattern PATTERN_SEARCH_CONTAINER = Pattern.compile("<img src=\"/images/icons/container/([^\\.]+)\\.gif\""); public final static Pattern PATTERN_SEARCH_GEOCODE = Pattern.compile("\\|\\W*(GC[0-9A-Z]+)[^\\|]*\\|"); - public final static Pattern PATTERN_SEARCH_ID = Pattern.compile("name=\"CID\"[^v]*value=\"([0-9]+)\""); - public final static Pattern PATTERN_SEARCH_FAVORITE = Pattern.compile("<span id=\"ctl00_ContentBody_dlResults_ctl[0-9]+_uxFavoritesValue\" title=\"[^\"]*\" class=\"favorite-rank\">([0-9]+)</span>"); - public final static Pattern PATTERN_SEARCH_TOTALCOUNT = Pattern.compile("<td class=\"PageBuilderWidget\"><span>Total Records[^<]*<b>(\\d+)<\\/b>"); + public final static Pattern PATTERN_SEARCH_ID = Pattern.compile("name=\"CID\"[^v]*value=\"(\\d+)\""); + public final static Pattern PATTERN_SEARCH_FAVORITE = Pattern.compile("favorite-rank\">([0-9,.]+)</span>"); + public final static Pattern PATTERN_SEARCH_TOTALCOUNT = Pattern.compile("<span>Total Records\\D*(\\d+)<"); public final static Pattern PATTERN_SEARCH_RECAPTCHA = Pattern.compile("<script[^>]*src=\"[^\"]*/recaptcha/api/challenge\\?k=([^\"]+)\"[^>]*>"); public final static Pattern PATTERN_SEARCH_RECAPTCHACHALLENGE = Pattern.compile("challenge : '([^']+)'"); + public final static Pattern PATTERN_SEARCH_HIDDEN_DATE = Pattern.compile("<span class=\"small\">([\\d-/]{6,10})</span>"); /** * Patterns for waypoints diff --git a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java index 4f2f8c4..2aa5c75 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java @@ -1,10 +1,10 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.Geocache; +import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.TrackableLog; -import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.ILoggingManager; import cgeo.geocaching.connector.ImageResult; @@ -80,7 +80,7 @@ public class GCLoggingManager implements ILoggingManager, LoaderManager.LoaderCa } @Override - public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) { + public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) { try { final ImmutablePair<StatusCode, String> postResult = GCParser.postLog(cache.getGeocode(), cache.getCacheId(), viewstates, logType, diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index 643caf5..4bc55fe 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -2,7 +2,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.Geocache; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; @@ -337,7 +337,7 @@ public class GCMap { Log.e("GCMap.searchByViewport: No cache parsed for viewport " + viewport); } else { - searchResult.addGeocodes(search.getGeocodes()); + searchResult.addSearchResult(search); } Tile.Cache.add(tile); } @@ -349,20 +349,21 @@ public class GCMap { } } + + // Check for vanished found caches + if (tiles.iterator().next().getZoomlevel() >= Tile.ZOOMLEVEL_MIN_PERSONALIZED) { + searchResult.addFilteredGeocodes(cgData.getCachedMissingFromSearch(searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1)); + } } - if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) { + if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY) && Settings.isPremiumMember()) { final Geopoint center = viewport.getCenter(); if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { //FIXME We don't have a RecaptchaReceiver!? SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null); if (search != null && !search.isEmpty()) { final Set<String> geocodes = search.getGeocodes(); - if (Settings.isPremiumMember()) { - lastSearchViewport = cgData.getBounds(geocodes); - } else { - lastSearchViewport = new Viewport(center, center); - } + lastSearchViewport = cgData.getBounds(geocodes); searchResult.addGeocodes(geocodes); } } diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index a58b2cc..e32f72d 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -5,7 +5,6 @@ import cgeo.geocaching.Image; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; import cgeo.geocaching.Trackable; import cgeo.geocaching.TrackableLog; import cgeo.geocaching.Waypoint; @@ -27,6 +26,7 @@ import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.loaders.RecaptchaReceiver; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.DirectionImage; import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.Log; @@ -53,6 +53,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; +import java.util.Date; import java.util.EnumSet; import java.util.GregorianCalendar; import java.util.List; @@ -120,6 +121,7 @@ public abstract class GCParser { final String[] rows = page.split("<tr class="); final int rows_count = rows.length; + int excludedCaches = 0; for (int z = 1; z < rows_count; z++) { final Geocache cache = new Geocache(); final String row = rows[z]; @@ -157,6 +159,7 @@ public abstract class GCParser { if (Settings.isExcludeDisabledCaches() && (cache.isDisabled() || cache.isArchived())) { // skip disabled and archived caches + excludedCaches++; continue; } @@ -176,7 +179,8 @@ public abstract class GCParser { // cache distance - estimated distance for basic members final String distance = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION_DISTANCE, false, 2, null, false); if (distance != null) { - cache.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits())); + cache.setDistance(DistanceParser.parseDistance(distance, + !Settings.isUseImperialUnits())); } // difficulty/terrain @@ -196,6 +200,19 @@ public abstract class GCParser { final String container = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_CONTAINER, false, 1, null, false); cache.setSize(CacheSize.getById(container)); + // date hidden, makes sorting event caches easier + 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); + if (date != null) { + cache.setHidden(date); + } + } catch (ParseException e) { + Log.e("Error parsing event date from search"); + } + } + // cache inventory final MatcherWrapper matcherTbs = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLES, row); String inventoryPre = null; @@ -237,7 +254,7 @@ public abstract class GCParser { // favorite count try { - result = TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_FAVORITE, false, 1, null, true); + result = getNumberString(TextUtils.getMatch(row, GCConstants.PATTERN_SEARCH_FAVORITE, false, 1, null, true)); if (null != result) { cache.setFavoritePoints(Integer.parseInt(result)); } @@ -252,7 +269,7 @@ public abstract class GCParser { try { final String result = TextUtils.getMatch(page, GCConstants.PATTERN_SEARCH_TOTALCOUNT, false, 1, null, true); if (null != result) { - searchResult.setTotal(Integer.parseInt(result)); + searchResult.setTotal(Integer.parseInt(result) - excludedCaches); } } catch (final NumberFormatException e) { Log.w("GCParser.parseSearch: Failed to parse cache count"); @@ -354,32 +371,41 @@ public abstract class GCParser { return searchResult; } - static SearchResult parseCacheFromText(final String page, final CancellableHandler handler) { + static SearchResult parseCacheFromText(final String pageIn, final CancellableHandler handler) { CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); - if (StringUtils.isBlank(page)) { + if (StringUtils.isBlank(pageIn)) { Log.e("GCParser.parseCache: No page given"); return null; } final SearchResult searchResult = new SearchResult(); - if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || page.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) { + if (pageIn.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || pageIn.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) { searchResult.setError(StatusCode.UNPUBLISHED_CACHE); return searchResult; } - if (page.contains(GCConstants.STRING_PREMIUMONLY_1) || page.contains(GCConstants.STRING_PREMIUMONLY_2)) { + if (pageIn.contains(GCConstants.STRING_PREMIUMONLY_1) || pageIn.contains(GCConstants.STRING_PREMIUMONLY_2)) { searchResult.setError(StatusCode.PREMIUM_ONLY); return searchResult; } - final String cacheName = Html.fromHtml(TextUtils.getMatch(page, GCConstants.PATTERN_NAME, true, "")).toString(); + final String cacheName = Html.fromHtml(TextUtils.getMatch(pageIn, GCConstants.PATTERN_NAME, true, "")).toString(); if (GCConstants.STRING_UNKNOWN_ERROR.equalsIgnoreCase(cacheName)) { searchResult.setError(StatusCode.UNKNOWN_ERROR); return searchResult; } + // first handle the content with line breaks, then trim everything for easier matching and reduced memory consumption in parsed fields + String personalNoteWithLineBreaks = ""; + MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_PERSONALNOTE, pageIn); + if (matcher.find()) { + personalNoteWithLineBreaks = matcher.group(1).trim(); + } + + final String page = TextUtils.replaceWhitespace(pageIn); + final Geocache cache = new Geocache(); cache.setDisabled(page.contains(GCConstants.STRING_DISABLED)); @@ -516,7 +542,7 @@ public abstract class GCParser { cache.checkFields(); // cache personal note - cache.setPersonalNote(TextUtils.getMatch(page, GCConstants.PATTERN_PERSONALNOTE, true, cache.getPersonalNote())); + cache.setPersonalNote(personalNoteWithLineBreaks); // cache short description cache.setShortDescription(TextUtils.getMatch(page, GCConstants.PATTERN_SHORTDESC, true, "")); @@ -626,7 +652,7 @@ public abstract class GCParser { while (matcherLog.find()) { final String typeStr = matcherLog.group(1); - final String countStr = matcherLog.group(2).replaceAll("[.,]", ""); + final String countStr = getNumberString(matcherLog.group(2)); if (StringUtils.isNotBlank(typeStr) && LogType.UNKNOWN != LogType.getByIconName(typeStr) @@ -736,6 +762,13 @@ public abstract class GCParser { return searchResult; } + private static String getNumberString(final String numberWithPunctuation) { + if (numberWithPunctuation == null) { + return null; + } + return numberWithPunctuation.replaceAll("[.,]", ""); + } + public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (search == null) { return search; @@ -862,7 +895,7 @@ public abstract class GCParser { } private static boolean isSearchForMyCaches(final String userName) { - if (userName.equalsIgnoreCase(Settings.getLogin().left)) { + if (userName.equalsIgnoreCase(Settings.getGcLogin().left)) { Log.i("Overriding users choice because of self search, downloading all caches."); return true; } @@ -1008,7 +1041,7 @@ 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)) { - Log.e("GCParser.postLogTrackable: Can not log in geocaching"); + Log.e("GCParser.postLog: Cannot log in geocaching"); return new ImmutablePair<StatusCode, String>(StatusCode.NOT_LOGGED_IN, ""); } @@ -1103,19 +1136,12 @@ public abstract class GCParser { * @return status code to indicate success or failure */ public static ImmutablePair<StatusCode, String> 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(); - - String page = Network.getResponseData(Network.getRequest(uri)); + final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").build().toString(); - if (!Login.getLoginStatus(page)) { - // Login.isActualLoginStatus() was wrong, we are not logged in - final StatusCode loginState = Login.login(); - if (loginState == StatusCode.NO_ERROR) { - page = Network.getResponseData(Network.getRequest(uri)); - } else { - Log.e("Image upload: No login (error: " + loginState + ')'); - return ImmutablePair.of(StatusCode.NOT_LOGGED_IN, null); - } + final String page = Login.getRequestLogged(uri, new Parameters("LID=", logId)); + if (StringUtils.isBlank(page)) { + Log.e("GCParser.uploadLogImage: No data from server"); + return new ImmutablePair<StatusCode, String>(StatusCode.UNKNOWN_ERROR, null); } final String[] viewstates = Login.getViewstates(page); @@ -1195,7 +1221,7 @@ public abstract class GCParser { 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)) { - Log.e("GCParser.postLogTrackable: Can not log in geocaching"); + Log.e("GCParser.postLogTrackable: Cannot log in geocaching"); return StatusCode.NOT_LOGGED_IN; } @@ -1430,7 +1456,8 @@ public abstract class GCParser { final String distance = TextUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_DISTANCE, false, null); if (null != distance) { try { - trackable.setDistance(DistanceParser.parseDistance(distance, Settings.isUseMetricUnits())); + trackable.setDistance(DistanceParser.parseDistance(distance, + !Settings.isUseImperialUnits())); } catch (final NumberFormatException e) { Log.e("GCParser.parseTrackable: Failed to parse distance", e); } @@ -1743,16 +1770,6 @@ public abstract class GCParser { } } - if (Settings.isElevationWanted()) { - if (CancellableHandler.isCancelled(handler)) { - return; - } - CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_elevation); - if (cache.getCoords() != null) { - cache.setElevation(cache.getCoords().getElevation()); - } - } - if (Settings.isRatingWanted()) { if (CancellableHandler.isCancelled(handler)) { return; diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java index d3a2959..ed44392 100644 --- a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java +++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java @@ -1,7 +1,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.Geocache; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.enumerations.CacheType; import android.graphics.Bitmap; @@ -21,7 +21,7 @@ public abstract class IconDecoder { private static final int CT_MEGAEVENT = 7; private static final int CT_CITO = 8; private static final int CT_WEBCAM = 9; - private static final int CT_WHEREIGO = 10; + private static final int CT_WHERIGO = 10; private static final int CT_VIRTUAL = 11; private static final int CT_LETTERBOX = 12; @@ -116,7 +116,7 @@ public abstract class IconDecoder { case CT_WEBCAM: cache.setType(CacheType.WEBCAM); return true; - case CT_WHEREIGO: + case CT_WHERIGO: cache.setType(CacheType.WHERIGO); return true; case CT_VIRTUAL: @@ -395,12 +395,12 @@ public abstract class IconDecoder { if (g < 71) { return CT_MYSTERY; } - return r < 153 ? CT_WHEREIGO : CT_WEBCAM; + return r < 153 ? CT_WHERIGO : CT_WEBCAM; } if (b < 167) { return r < 157 ? CT_TRADITIONAL : CT_WEBCAM; } - return CT_WHEREIGO; + return CT_WHERIGO; } if (g < 199) { if (r < 142) { @@ -450,7 +450,7 @@ public abstract class IconDecoder { if (b < 252) { if (r < 243) { if (r < 225) { - return CT_WHEREIGO; + return CT_WHERIGO; } if (b < 232) { if (g < 228) { @@ -459,14 +459,14 @@ public abstract class IconDecoder { return r < 231 ? CT_VIRTUAL : CT_TRADITIONAL; } if (r < 236) { - return CT_WHEREIGO; + return CT_WHERIGO; } - return r < 240 ? CT_WEBCAM : CT_WHEREIGO; + return r < 240 ? CT_WEBCAM : CT_WHERIGO; } if (g < 247) { return r < 245 ? CT_WEBCAM : CT_FOUND; } - return CT_WHEREIGO; + return CT_WHERIGO; } return CT_LETTERBOX; } diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java index 413cda4..4b4c93f 100644 --- a/main/src/cgeo/geocaching/connector/gc/Login.java +++ b/main/src/cgeo/geocaching/connector/gc/Login.java @@ -1,16 +1,16 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.cgeoapplication; 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.utils.TextUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; +import cgeo.geocaching.utils.TextUtils; import ch.boye.httpclientandroidlib.HttpResponse; @@ -52,9 +52,9 @@ public abstract class Login { "dd/MM/yyyy" }; - Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>(); + final Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>(); - for (String format : formats) { + for (final String format : formats) { map.put(format, new SimpleDateFormat(format, Locale.ENGLISH)); } @@ -66,7 +66,7 @@ public abstract class Login { } private static StatusCode login(boolean retry) { - final ImmutablePair<String, String> login = Settings.getLogin(); + final ImmutablePair<String, String> login = Settings.getGcLogin(); if (login == null || StringUtils.isEmpty(login.left) || StringUtils.isEmpty(login.right)) { Login.setActualStatus(cgeoapplication.getInstance().getString(R.string.err_login)); @@ -147,8 +147,8 @@ public abstract class Login { } public static StatusCode logout() { - HttpResponse logoutResponse = Network.getRequest("https://www.geocaching.com/login/default.aspx?RESET=Y&redir=http%3a%2f%2fwww.geocaching.com%2fdefault.aspx%3f"); - String logoutData = Network.getResponseData(logoutResponse); + 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; } @@ -211,7 +211,7 @@ public abstract class Login { int cachesCount = 0; try { cachesCount = Integer.parseInt(TextUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", "")); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { Log.e("getLoginStatus: bad cache count", e); } setActualCachesFound(cachesCount); @@ -276,7 +276,7 @@ public abstract class Login { } // No match? There may be no avatar set by user. Log.d("No avatar set for user"); - } catch (Exception e) { + } catch (final Exception e) { Log.w("Error when retrieving user avatar", e); } return null; @@ -294,7 +294,7 @@ public abstract class Login { return; } - String customDate = TextUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null); + final String customDate = TextUtils.getMatch(result, GCConstants.PATTERN_CUSTOMDATE, true, null); if (null != customDate) { Settings.setGcCustomDate(customDate); } @@ -310,14 +310,14 @@ public abstract class Login { if (gcCustomDateFormats.containsKey(format)) { try { return gcCustomDateFormats.get(format).parse(trimmed); - } catch (ParseException e) { + } catch (final ParseException e) { } } - for (SimpleDateFormat sdf : gcCustomDateFormats.values()) { + for (final SimpleDateFormat sdf : gcCustomDateFormats.values()) { try { return sdf.parse(trimmed); - } catch (ParseException e) { + } catch (final ParseException e) { } } @@ -347,7 +347,7 @@ public abstract class Login { return true; } - for (String s : a) { + for (final String s : a) { if (StringUtils.isNotEmpty(s)) { return false; } @@ -373,24 +373,24 @@ public abstract class Login { if (matcherViewstateCount.find()) { try { count = Integer.parseInt(matcherViewstateCount.group(1)); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { Log.e("getViewStates", e); } } - String[] viewstates = new String[count]; + final String[] viewstates = new String[count]; // Get the viewstates final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page); while (matcherViewstates.find()) { - String sno = matcherViewstates.group(1); // number of viewstate + final String sno = matcherViewstates.group(1); // number of viewstate int no; if (StringUtils.isEmpty(sno)) { no = 0; } else { try { no = Integer.parseInt(sno); - } catch (NumberFormatException e) { + } catch (final NumberFormatException e) { Log.e("getViewStates", e); no = 0; } @@ -436,17 +436,17 @@ public abstract class Login { * @return */ public static String postRequestLogged(final String uri, final Parameters params) { - HttpResponse response = Network.postRequest(uri, params); - String data = Network.getResponseData(response); + final String data = Network.getResponseData(Network.postRequest(uri, params)); - if (!getLoginStatus(data)) { - if (login() == StatusCode.NO_ERROR) { - response = Network.postRequest(uri, params); - data = Network.getResponseData(response); - } else { - Log.i("Working as guest."); - } + if (getLoginStatus(data)) { + return data; + } + + if (login() == StatusCode.NO_ERROR) { + return Network.getResponseData(Network.postRequest(uri, params)); } + + Log.i("Working as guest."); return data; } @@ -458,20 +458,31 @@ public abstract class Login { * @return */ public static String getRequestLogged(final String uri, final Parameters params) { - final String data = Network.getResponseData(Network.getRequest(uri, params)); + final String data = Network.getResponseData(Network.getRequest(uri, params), canRemoveWhitespace(uri)); if (getLoginStatus(data)) { return data; } if (login() == StatusCode.NO_ERROR) { - return Network.getResponseData(Network.getRequest(uri, params)); + 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); diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index dd7f352..3177f2c 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -37,6 +37,7 @@ public class Tile { public static final int TILE_SIZE = 256; public static final int ZOOMLEVEL_MAX = 18; public static final int ZOOMLEVEL_MIN = 0; + public static final int ZOOMLEVEL_MIN_PERSONALIZED = 12; static final int[] NUMBER_OF_TILES = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1]; static final int[] NUMBER_OF_PIXELS = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1]; @@ -252,6 +253,10 @@ public class Tile { return viewPort.contains(point); } + public Viewport getViewport() { + return viewPort; + } + /** * Calculate needed tiles for the given viewport to cover it with * max 2x2 tiles @@ -319,6 +324,10 @@ public class Tile { public static void add(final Tile tile) { tileCache.put(tile.hashCode(), tile); } + + public static void clear() { + tileCache.clear(); + } } } diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java index 4c6db97..5ca2d28 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java @@ -2,13 +2,14 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.Geocache; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.ILoggingManager; +import cgeo.geocaching.connector.capability.ILogin; import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.capability.ISearchByViewPort; -import cgeo.geocaching.connector.oc.OkapiClient.UserInfo; +import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.utils.CryptUtils; @@ -16,11 +17,13 @@ import cgeo.geocaching.utils.CryptUtils; import org.apache.commons.lang3.StringUtils; import android.app.Activity; +import android.content.Context; +import android.os.Handler; -public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort { +public class OCApiLiveConnector extends OCApiConnector implements ISearchByCenter, ISearchByViewPort, ILogin { private String cS; - private UserInfo userInfo = new UserInfo(StringUtils.EMPTY, 0, false); + private UserInfo userInfo = new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.NOT_RETRIEVED); public OCApiLiveConnector(String name, String host, String prefix, int cKResId, int cSResId, ApiSupport apiSupport) { super(name, host, prefix, CryptUtils.rot13(cgeoapplication.getInstance().getResources().getString(cKResId)), apiSupport); @@ -104,16 +107,33 @@ public class OCApiLiveConnector extends OCApiConnector implements ISearchByCente return getSupportedAuthLevel() == OAuthLevel.Level3; } - public boolean retrieveUserInfo() { - userInfo = OkapiClient.getUserInfo(this); - return userInfo.isRetrieveSuccessful(); + @Override + public boolean login(Handler handler, Context fromActivity) { + if (supportsPersonalization()) { + userInfo = OkapiClient.getUserInfo(this); + } else { + userInfo = new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.NOT_SUPPORTED); + } + return userInfo.getStatus() == UserInfoStatus.SUCCESSFUL; } - public Object getUserName() { + @Override + public String getUserName() { return userInfo.getName(); } + @Override public int getCachesFound() { return userInfo.getFinds(); } + + @Override + public String getLoginStatusString() { + return cgeoapplication.getInstance().getString(userInfo.getStatus().resId); + } + + @Override + public boolean isLoggedIn() { + return userInfo.getStatus() == UserInfoStatus.SUCCESSFUL; + } } diff --git a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java index 779c1c5..08d796e 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java @@ -1,7 +1,7 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.network.OAuthAuthorizationActivity; @@ -9,8 +9,6 @@ import org.apache.commons.lang3.tuple.ImmutablePair; public class OCAuthorizationActivity extends OAuthAuthorizationActivity { - private final int siteResId = R.string.auth_ocde; - public OCAuthorizationActivity() { super("www.opencaching.de", "/okapi/services/oauth/request_token", @@ -38,7 +36,7 @@ public class OCAuthorizationActivity extends OAuthAuthorizationActivity { @Override protected String getAuthTitle() { - return res.getString(siteResId); + return res.getString(R.string.auth_ocde); } @Override diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java index 01738c0..29cdd10 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java @@ -12,7 +12,7 @@ public class OCConnector extends AbstractConnector { private final String host; private final String name; private final Pattern codePattern; - private static final Pattern gpxZipFilePattern = Pattern.compile("oc[a-z]{2,3}\\d{5,}\\.zip", Pattern.CASE_INSENSITIVE); + private static final Pattern GPX_ZIP_FILE_PATTERN = Pattern.compile("oc[a-z]{2,3}\\d{5,}\\.zip", Pattern.CASE_INSENSITIVE); public OCConnector(final String name, final String host, final String prefix) { this.name = name; @@ -45,7 +45,7 @@ public class OCConnector extends AbstractConnector { @Override public boolean isZippedGPXFile(String fileName) { - return gpxZipFilePattern.matcher(fileName).matches(); + return GPX_ZIP_FILE_PATTERN.matcher(fileName).matches(); } @Override diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java index 3c99bc9..6959adf 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java @@ -4,7 +4,6 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.Image; import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; -import cgeo.geocaching.Settings; import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; @@ -14,6 +13,7 @@ import cgeo.geocaching.connector.LogResult; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.oc.OCApiConnector.ApiSupport; import cgeo.geocaching.connector.oc.OCApiConnector.OAuthLevel; +import cgeo.geocaching.connector.oc.UserInfo.UserInfoStatus; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.CacheSize; import cgeo.geocaching.enumerations.CacheType; @@ -27,6 +27,7 @@ import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.OAuth; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -50,16 +51,16 @@ import java.util.Locale; import java.util.Map; import java.util.TimeZone; -final public class OkapiClient { +final class OkapiClient { private static final char SEPARATOR = '|'; private static final String SEPARATOR_STRING = Character.toString(SEPARATOR); - private static final SimpleDateFormat logDateFormat; - + private static final SimpleDateFormat LOG_DATE_FORMAT; static { - logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.US); - logDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + LOG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.US); + LOG_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); } + private static final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault()); private static final String CACHE_ATTRNAMES = "attrnames"; private static final String WPT_LOCATION = "location"; @@ -93,6 +94,8 @@ final public class OkapiClient { private static final String CACHE_LOCATION = "location"; private static final String CACHE_NAME = "name"; private static final String CACHE_CODE = "code"; + private static final String CACHE_REQ_PASSWORD = "req_passwd"; + private static final String CACHE_MY_NOTES = "my_notes"; private static final String LOG_TYPE = "type"; private static final String LOG_COMMENT = "comment"; @@ -108,9 +111,9 @@ final public class OkapiClient { // Additional: additional fields for full cache (L3 - only for level 3 auth, current - only for connectors with current api) private static final String SERVICE_CACHE_CORE_FIELDS = "code|name|location|type|status|difficulty|terrain|size"; private static final String SERVICE_CACHE_CORE_L3_FIELDS = "is_found"; - private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|alt_wpts|attrnames"; + private static final String SERVICE_CACHE_ADDITIONAL_FIELDS = "owner|founds|notfounds|rating|rating_votes|recommendations|description|hint|images|latest_logs|date_hidden|alt_wpts|attrnames|req_passwd"; private static final String SERVICE_CACHE_ADDITIONAL_CURRENT_FIELDS = "gc_code|attribution_note"; - private static final String SERVICE_CACHE_ADDITIONAL_L3_FIELDS = "is_watched"; + private static final String SERVICE_CACHE_ADDITIONAL_L3_FIELDS = "is_watched|my_notes"; private static final String METHOD_SEARCH_NEAREST = "services/caches/search/nearest"; private static final String METHOD_SEARCH_BBOX = "services/caches/search/bbox"; @@ -118,12 +121,12 @@ final public class OkapiClient { public static Geocache getCache(final String geoCode) { final Parameters params = new Parameters("cache_code", geoCode); - IConnector connector = ConnectorFactory.getConnector(geoCode); + final IConnector connector = ConnectorFactory.getConnector(geoCode); if (!(connector instanceof OCApiConnector)) { return null; } - OCApiConnector ocapiConn = (OCApiConnector) connector; + final OCApiConnector ocapiConn = (OCApiConnector) connector; params.add("fields", getFullFields(ocapiConn)); params.add("attribution_append", "none"); @@ -137,17 +140,19 @@ final public class OkapiClient { return parseCache(data); } - public static List<Geocache> getCachesAround(final Geopoint center, OCApiConnector connector) { - String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center); + public static List<Geocache> getCachesAround(final Geopoint center, final OCApiConnector connector) { + final String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center); final Parameters params = new Parameters("search_method", METHOD_SEARCH_NEAREST); final Map<String, String> valueMap = new LinkedHashMap<String, String>(); valueMap.put("center", centerString); valueMap.put("limit", "20"); - addFilterParams(valueMap, connector); + return requestCaches(connector, params, valueMap); + } + private static List<Geocache> requestCaches(final OCApiConnector connector, final Parameters params, final Map<String, String> valueMap) { + addFilterParams(valueMap, connector); params.add("search_params", new JSONObject(valueMap).toString()); - addRetrieveParams(params, connector); final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params); @@ -160,13 +165,13 @@ final public class OkapiClient { } // Assumes level 3 OAuth - public static List<Geocache> getCachesBBox(final Viewport viewport, OCApiConnector connector) { + public static List<Geocache> getCachesBBox(final Viewport viewport, final OCApiConnector connector) { if (viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) { return Collections.emptyList(); } - String bboxString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.bottomLeft) + final String bboxString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.bottomLeft) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.bottomLeft) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, viewport.topRight) + SEPARATOR + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, viewport.topRight); @@ -174,22 +179,10 @@ final public class OkapiClient { final Map<String, String> valueMap = new LinkedHashMap<String, String>(); valueMap.put("bbox", bboxString); - addFilterParams(valueMap, connector); - - params.add("search_params", new JSONObject(valueMap).toString()); - - addRetrieveParams(params, connector); - - final JSONObject data = request(connector, OkapiService.SERVICE_SEARCH_AND_RETRIEVE, params); - - if (data == null) { - return Collections.emptyList(); - } - - return parseCaches(data); + return requestCaches(connector, params, valueMap); } - public static boolean setWatchState(final Geocache cache, final boolean watched, OCApiConnector connector) { + public static boolean setWatchState(final Geocache cache, final boolean watched, final OCApiConnector connector) { final Parameters params = new Parameters("cache_code", cache.getGeocode()); params.add("watched", watched ? "true" : "false"); @@ -204,15 +197,18 @@ final public class OkapiClient { return true; } - public static LogResult postLog(final Geocache cache, LogType logType, Calendar date, String log, OCApiConnector connector) { + public static LogResult postLog(final Geocache cache, final LogType logType, final Calendar date, final String log, final String logPassword, final OCApiConnector connector) { final Parameters params = new Parameters("cache_code", cache.getGeocode()); params.add("logtype", logType.oc_type); params.add("comment", log); params.add("comment_format", "plaintext"); - params.add("when", logDateFormat.format(date.getTime())); + params.add("when", LOG_DATE_FORMAT.format(date.getTime())); if (logType.equals(LogType.NEEDS_MAINTENANCE)) { params.add("needs_maintenance", "true"); } + if (logPassword != null) { + params.add("password", logPassword); + } final JSONObject data = request(connector, OkapiService.SERVICE_SUBMIT_LOG, params); @@ -226,7 +222,7 @@ final public class OkapiClient { } return new LogResult(StatusCode.LOG_POST_ERROR, ""); - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.postLog", e); } return new LogResult(StatusCode.LOG_POST_ERROR, ""); @@ -243,19 +239,20 @@ final public class OkapiClient { // Get and iterate result list final JSONObject cachesResponse = response.getJSONObject("results"); if (cachesResponse != null) { - List<Geocache> caches = new ArrayList<Geocache>(cachesResponse.length()); + final List<Geocache> caches = new ArrayList<Geocache>(cachesResponse.length()); @SuppressWarnings("unchecked") + final Iterator<String> keys = cachesResponse.keys(); while (keys.hasNext()) { - String key = keys.next(); - Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key)); + final String key = keys.next(); + final Geocache cache = parseSmallCache(cachesResponse.getJSONObject(key)); if (cache != null) { caches.add(cache); } } return caches; } - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.parseCachesResult", e); } return Collections.emptyList(); @@ -269,7 +266,7 @@ final public class OkapiClient { parseCoreCache(response, cache); cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE)); - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.parseSmallCache", e); } return cache; @@ -297,9 +294,9 @@ final public class OkapiClient { cache.setFavoritePoints(response.getInt(CACHE_RECOMMENDATIONS)); // not used: req_password // Prepend gc-link to description if available - StringBuilder description = new StringBuilder(500); + final StringBuilder description = new StringBuilder(500); if (!response.isNull("gc_code")) { - String gccode = response.getString("gc_code"); + final String gccode = response.getString("gc_code"); description.append(cgeoapplication.getInstance().getResources() .getString(R.string.cache_listed_on, GCConnector.getInstance().getName())) .append(": <a href=\"http://coord.info/") @@ -318,7 +315,7 @@ final public class OkapiClient { final JSONArray images = response.getJSONArray(CACHE_IMAGES); if (images != null) { for (int i = 0; i < images.length(); i++) { - JSONObject imageResponse = images.getJSONObject(i); + final JSONObject imageResponse = images.getJSONObject(i); if (imageResponse.getBoolean(CACHE_IMAGE_IS_SPOILER)) { final String title = imageResponse.getString(CACHE_IMAGE_CAPTION); final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode()); @@ -336,11 +333,15 @@ final public class OkapiClient { if (!response.isNull(CACHE_IS_WATCHED)) { cache.setOnWatchlist(response.getBoolean(CACHE_IS_WATCHED)); } + if (!response.isNull(CACHE_MY_NOTES)) { + cache.setPersonalNote(response.getString(CACHE_MY_NOTES)); + } + cache.setLogPasswordRequired(response.getBoolean(CACHE_REQ_PASSWORD)); cache.setDetailedUpdatedNow(); // save full detailed caches cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB)); - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.parseCache", e); } return cache; @@ -366,7 +367,7 @@ final public class OkapiClient { } } - private static String absoluteUrl(String url, String geocode) { + private static String absoluteUrl(final String url, final String geocode) { final Uri uri = Uri.parse(url); if (!uri.isAbsolute()) { @@ -379,16 +380,16 @@ final public class OkapiClient { return url; } - private static String parseUser(JSONObject user) throws JSONException { + private static String parseUser(final JSONObject user) throws JSONException { return user.getString(USER_USERNAME); } - private static List<LogEntry> parseLogs(JSONArray logsJSON) { + private static List<LogEntry> parseLogs(final JSONArray logsJSON) { List<LogEntry> result = null; for (int i = 0; i < logsJSON.length(); i++) { try { - JSONObject logResponse = logsJSON.getJSONObject(i); - LogEntry log = new LogEntry( + final JSONObject logResponse = logsJSON.getJSONObject(i); + final LogEntry log = new LogEntry( parseUser(logResponse.getJSONObject(LOG_USER)), parseDate(logResponse.getString(LOG_DATE)).getTime(), parseLogType(logResponse.getString(LOG_TYPE)), @@ -397,23 +398,23 @@ final public class OkapiClient { result = new ArrayList<LogEntry>(); } result.add(log); - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.parseLogs", e); } } return result; } - private static List<Waypoint> parseWaypoints(JSONArray wptsJson) { + private static List<Waypoint> parseWaypoints(final JSONArray wptsJson) { List<Waypoint> result = null; for (int i = 0; i < wptsJson.length(); i++) { try { - JSONObject wptResponse = wptsJson.getJSONObject(i); - Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME), + final JSONObject wptResponse = wptsJson.getJSONObject(i); + final Waypoint wpt = new Waypoint(wptResponse.getString(WPT_NAME), parseWptType(wptResponse.getString(WPT_TYPE)), false); wpt.setNote(wptResponse.getString(WPT_DESCRIPTION)); - Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION)); + final Geopoint pt = parseCoords(wptResponse.getString(WPT_LOCATION)); if (pt != null) { wpt.setCoords(pt); } @@ -421,14 +422,14 @@ final public class OkapiClient { result = new ArrayList<Waypoint>(); } result.add(wpt); - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.parseWaypoints", e); } } return result; } - private static LogType parseLogType(String logType) { + private static LogType parseLogType(final String logType) { if ("Found it".equalsIgnoreCase(logType)) { return LogType.FOUND_IT; } @@ -438,7 +439,7 @@ final public class OkapiClient { return LogType.NOTE; } - private static WaypointType parseWptType(String wptType) { + private static WaypointType parseWptType(final String wptType) { if ("parking".equalsIgnoreCase(wptType)) { return WaypointType.PARKING; } @@ -464,11 +465,10 @@ final public class OkapiClient { } private static Date parseDate(final String date) { - final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault()); final String strippedDate = date.replaceAll("\\+0([0-9]){1}\\:00", "+0$100"); try { return ISO8601DATEFORMAT.parse(strippedDate); - } catch (ParseException e) { + } catch (final ParseException e) { Log.e("OkapiClient.parseDate", e); } return null; @@ -484,19 +484,19 @@ final public class OkapiClient { return null; } - private static List<String> parseAttributes(JSONArray nameList) { + private static List<String> parseAttributes(final JSONArray nameList) { - List<String> result = new ArrayList<String>(); + final List<String> result = new ArrayList<String>(); for (int i = 0; i < nameList.length(); i++) { try { - String name = nameList.getString(i); - CacheAttribute attr = CacheAttribute.getByOcId(AttributeParser.getOcDeId(name)); + final String name = nameList.getString(i); + final CacheAttribute attr = CacheAttribute.getByOcId(AttributeParser.getOcDeId(name)); if (attr != null) { result.add(attr.rawName); } - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.parseAttributes", e); } } @@ -517,7 +517,7 @@ final public class OkapiClient { double size = 0; try { size = response.getDouble(CACHE_SIZE); - } catch (JSONException e) { + } catch (final JSONException e) { Log.e("OkapiClient.getCacheSize", e); } switch ((int) Math.round(size)) { @@ -565,7 +565,7 @@ final public class OkapiClient { return CacheType.UNKNOWN; } - private static String getCoreFields(OCApiConnector connector) { + private static String getCoreFields(final OCApiConnector connector) { if (connector == null) { Log.e("OkapiClient.getCoreFields called with invalid connector"); return StringUtils.EMPTY; @@ -578,13 +578,13 @@ final public class OkapiClient { return SERVICE_CACHE_CORE_FIELDS; } - private static String getFullFields(OCApiConnector connector) { + private static String getFullFields(final OCApiConnector connector) { if (connector == null) { Log.e("OkapiClient.getFullFields called with invalid connector"); return StringUtils.EMPTY; } - StringBuilder res = new StringBuilder(500); + final StringBuilder res = new StringBuilder(500); res.append(SERVICE_CACHE_CORE_FIELDS); res.append(SEPARATOR).append(SERVICE_CACHE_ADDITIONAL_FIELDS); @@ -629,7 +629,7 @@ final public class OkapiClient { return "en"; } - private static void addFilterParams(final Map<String, String> valueMap, OCApiConnector connector) { + private static void addFilterParams(final Map<String, String> valueMap, final OCApiConnector connector) { if (!Settings.isExcludeDisabledCaches()) { valueMap.put("status", "Available|Temporarily unavailable"); } @@ -642,13 +642,13 @@ final public class OkapiClient { } } - private static void addRetrieveParams(final Parameters params, OCApiConnector connector) { + private static void addRetrieveParams(final Parameters params, final OCApiConnector connector) { params.add("retr_method", METHOD_RETRIEVE_CACHES); params.add("retr_params", "{\"fields\": \"" + getCoreFields(connector) + "\"}"); params.add("wrap", "true"); } - private static String getFilterFromType(CacheType cacheType) { + private static String getFilterFromType(final CacheType cacheType) { switch (cacheType) { case EVENT: return "Event"; @@ -667,67 +667,40 @@ final public class OkapiClient { } } - public static UserInfo getUserInfo(OCApiLiveConnector connector) { + public static UserInfo getUserInfo(final OCApiLiveConnector connector) { final Parameters params = new Parameters("fields", USER_INFO_FIELDS); final JSONObject data = request(connector, OkapiService.SERVICE_USER, params); if (data == null) { - return new UserInfo(StringUtils.EMPTY, 0, false); + return new UserInfo(StringUtils.EMPTY, 0, UserInfoStatus.FAILED); } String name = StringUtils.EMPTY; - int finds = 0; - boolean success = true; + boolean successUserName = false; if (!data.isNull(USER_USERNAME)) { try { name = data.getString(USER_USERNAME); - } catch (JSONException e) { + successUserName = true; + } catch (final JSONException e) { Log.e("OkapiClient.getUserInfo - name", e); - success = false; } - } else { - success = false; } + int finds = 0; + boolean successFinds = false; + if (!data.isNull(USER_CACHES_FOUND)) { try { finds = data.getInt(USER_CACHES_FOUND); - } catch (JSONException e) { + successFinds = true; + } catch (final JSONException e) { Log.e("OkapiClient.getUserInfo - finds", e); - success = false; } - } else { - success = false; - } - - return new UserInfo(name, finds, success); - } - - public static class UserInfo { - - private final String name; - private final int finds; - private final boolean retrieveSuccessful; - - UserInfo(String name, int finds, boolean retrieveSuccessful) { - this.name = name; - this.finds = finds; - this.retrieveSuccessful = retrieveSuccessful; } - public String getName() { - return name; - } - - public int getFinds() { - return finds; - } - - public boolean isRetrieveSuccessful() { - return retrieveSuccessful; - } + return new UserInfo(name, finds, successUserName && successFinds ? UserInfoStatus.SUCCESSFUL : UserInfoStatus.FAILED); } } diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java index 8a94218..c995975 100644 --- a/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java +++ b/main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java @@ -1,8 +1,8 @@ package cgeo.geocaching.connector.oc; import cgeo.geocaching.Geocache; -import cgeo.geocaching.TrackableLog; import cgeo.geocaching.LogCacheActivity; +import cgeo.geocaching.TrackableLog; import cgeo.geocaching.connector.ILoggingManager; import cgeo.geocaching.connector.ImageResult; import cgeo.geocaching.connector.LogResult; @@ -19,14 +19,14 @@ import java.util.List; public class OkapiLoggingManager implements ILoggingManager { - private final OCApiConnector connector; + private final OCApiLiveConnector connector; private final Geocache cache; private LogCacheActivity activity; - private final static List<LogType> standardLogTypes = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE, LogType.NEEDS_MAINTENANCE); + private final static List<LogType> standardLogTypes = Arrays.asList(LogType.FOUND_IT, LogType.DIDNT_FIND_IT, LogType.NOTE); private final static List<LogType> eventLogTypes = Arrays.asList(LogType.WILL_ATTEND, LogType.ATTENDED, LogType.NOTE); - public OkapiLoggingManager(Activity activity, OCApiConnector connector, Geocache cache) { + public OkapiLoggingManager(Activity activity, OCApiLiveConnector connector, Geocache cache) { this.connector = connector; this.cache = cache; this.activity = (LogCacheActivity) activity; @@ -38,8 +38,10 @@ public class OkapiLoggingManager implements ILoggingManager { } @Override - public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, List<TrackableLog> trackableLogs) { - return OkapiClient.postLog(cache, logType, date, log, connector); + public LogResult postLog(Geocache cache, LogType logType, Calendar date, String log, String logPassword, List<TrackableLog> trackableLogs) { + final LogResult result = OkapiClient.postLog(cache, logType, date, log, logPassword, connector); + connector.login(null, null); + return result; } @Override diff --git a/main/src/cgeo/geocaching/connector/oc/UserInfo.java b/main/src/cgeo/geocaching/connector/oc/UserInfo.java new file mode 100644 index 0000000..0dc0440 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/oc/UserInfo.java @@ -0,0 +1,41 @@ +package cgeo.geocaching.connector.oc; + +import cgeo.geocaching.R; + +public class UserInfo { + + public enum UserInfoStatus { + NOT_RETRIEVED(R.string.init_login_popup_working), + SUCCESSFUL(R.string.init_login_popup_ok), + FAILED(R.string.init_login_popup_failed), + NOT_SUPPORTED(R.string.init_login_popup_not_authorized); + + public final int resId; + + UserInfoStatus(int resId) { + this.resId = resId; + } + } + + private final String name; + private final int finds; + private final UserInfoStatus status; + + UserInfo(String name, int finds, UserInfoStatus status) { + this.name = name; + this.finds = finds; + this.status = status; + } + + public String getName() { + return name; + } + + public int getFinds() { + return finds; + } + + public UserInfoStatus getStatus() { + return status; + } +} diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java index eec07e3..af33bb6 100644 --- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java +++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java @@ -3,7 +3,7 @@ package cgeo.geocaching.connector.ox; import cgeo.geocaching.Geocache; import cgeo.geocaching.ICache; import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; +import cgeo.geocaching.settings.Settings; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.capability.ISearchByGeocode; diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java index 9ca7716..0dac6cc 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java @@ -10,7 +10,7 @@ public class TravelBugConnector extends AbstractTrackableConnector { /** * TB codes really start with TB1, there is no padding or minimum length */ - private final static Pattern PATTERN_TB_CODE = Pattern.compile("TB[0-9A-Z]+", Pattern.CASE_INSENSITIVE); + private final static Pattern PATTERN_TB_CODE = Pattern.compile("(TB[0-9A-Z]+)|([0-9A-Z]{6})", Pattern.CASE_INSENSITIVE); @Override public boolean canHandleTrackable(String geocode) { @@ -31,4 +31,20 @@ public class TravelBugConnector extends AbstractTrackableConnector { public Trackable searchTrackable(String geocode, String guid, String id) { return GCParser.searchTrackable(geocode, guid, id); } + + /** + * initialization on demand holder pattern + */ + private static class Holder { + private static final TravelBugConnector INSTANCE = new TravelBugConnector(); + } + + private TravelBugConnector() { + // singleton + } + + public static TravelBugConnector getInstance() { + return Holder.INSTANCE; + } + }
\ No newline at end of file |
