aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/connector
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/connector')
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java29
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java40
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java20
-rw-r--r--main/src/cgeo/geocaching/connector/ILoggingManager.java13
-rw-r--r--main/src/cgeo/geocaching/connector/NoLoggingManager.java2
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ILogin.java57
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java62
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java11
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCLoggingManager.java6
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java17
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java91
-rw-r--r--main/src/cgeo/geocaching/connector/gc/IconDecoder.java18
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java69
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java9
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiLiveConnector.java36
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCAuthorizationActivity.java6
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCConnector.java4
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java187
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiLoggingManager.java14
-rw-r--r--main/src/cgeo/geocaching/connector/oc/UserInfo.java41
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OXConnector.java2
-rw-r--r--main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java18
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