aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/connector/gc/GCParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/connector/gc/GCParser.java')
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java420
1 files changed, 248 insertions, 172 deletions
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 158a201..9707e06 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -1,14 +1,15 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.Geocache;
+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.cgCache;
-import cgeo.geocaching.cgImage;
-import cgeo.geocaching.cgTrackable;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -28,8 +29,9 @@ import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.DirectionImage;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
-import cgeo.geocaching.utils.LazyInitializedList;
+import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -37,18 +39,15 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.net.Uri;
import android.text.Html;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.StrikethroughSpan;
-import java.net.URLDecoder;
+import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -58,7 +57,6 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
-import java.util.regex.Matcher;
public abstract class GCParser {
private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
@@ -71,8 +69,6 @@ public abstract class GCParser {
}
final List<String> cids = new ArrayList<String>();
- String recaptchaChallenge = null;
- String recaptchaText = null;
String page = pageContent;
final SearchResult searchResult = new SearchResult();
@@ -81,6 +77,7 @@ public abstract class GCParser {
// recaptcha
AbstractSearchThread thread = AbstractSearchThread.getCurrentInstance();
+ String recaptchaChallenge = null;
if (showCaptcha) {
String recaptchaJsParam = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null);
@@ -124,7 +121,7 @@ public abstract class GCParser {
final int rows_count = rows.length;
for (int z = 1; z < rows_count; z++) {
- final cgCache cache = new cgCache();
+ final Geocache cache = new Geocache();
String row = rows[z];
// check for cache type presence
@@ -133,7 +130,7 @@ public abstract class GCParser {
}
try {
- final Matcher matcherGuidAndDisabled = GCConstants.PATTERN_SEARCH_GUIDANDDISABLED.matcher(row);
+ final MatcherWrapper matcherGuidAndDisabled = new MatcherWrapper(GCConstants.PATTERN_SEARCH_GUIDANDDISABLED, row);
while (matcherGuidAndDisabled.find()) {
if (matcherGuidAndDisabled.groupCount() > 0) {
@@ -163,29 +160,32 @@ public abstract class GCParser {
continue;
}
- String inventoryPre = null;
-
- cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true).toUpperCase());
+ cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true));
// cache type
cache.setType(CacheType.getByPattern(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true)));
// cache direction - image
if (Settings.getLoadDirImg()) {
- cache.setDirectionImg(URLDecoder.decode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION, true, 1, cache.getDirectionImg(), true)));
+ cache.setDirectionImg(Network.decode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION, true, 1, cache.getDirectionImg(), true)));
}
// cache inventory
- final Matcher matcherTbs = GCConstants.PATTERN_SEARCH_TRACKABLES.matcher(row);
+ final MatcherWrapper matcherTbs = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLES, row);
+ String inventoryPre = null;
while (matcherTbs.find()) {
if (matcherTbs.groupCount() > 0) {
- cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1)));
+ try {
+ cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1)));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing trackables count", e);
+ }
inventoryPre = matcherTbs.group(2);
}
}
if (StringUtils.isNotBlank(inventoryPre)) {
- final Matcher matcherTbsInside = GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE.matcher(inventoryPre);
+ final MatcherWrapper matcherTbsInside = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE, inventoryPre);
while (matcherTbsInside.find()) {
if (matcherTbsInside.groupCount() == 2 &&
matcherTbsInside.group(2) != null &&
@@ -202,9 +202,6 @@ public abstract class GCParser {
// found it
cache.setFound(row.contains("/images/icons/16/found.png"));
- // own it
- cache.setOwn(row.contains("/images/icons/16/placed.png"));
-
// id
String result = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_ID, null);
if (null != result) {
@@ -222,16 +219,6 @@ public abstract class GCParser {
Log.w("GCParser.parseSearch: Failed to parse favourite count");
}
- if (cache.getNameSp() == null) {
- cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName()));
- if (cache.isDisabled() || cache.isArchived()) { // strike
- cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- if (cache.isArchived()) {
- cache.getNameSp().setSpan(new ForegroundColorSpan(cgeoapplication.getInstance().getResources().getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
searchResult.addCache(cache);
}
@@ -245,6 +232,7 @@ public abstract class GCParser {
Log.w("GCParser.parseSearch: Failed to parse cache count");
}
+ String recaptchaText = null;
if (thread != null && recaptchaChallenge != null) {
if (thread.getText() == null) {
thread.waitForUser();
@@ -253,7 +241,7 @@ public abstract class GCParser {
recaptchaText = thread.getText();
}
- if (cids.size() > 0 && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) {
+ if (!cids.isEmpty() && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) {
Log.i("Trying to get .loc for " + cids.size() + " caches");
try {
@@ -295,14 +283,14 @@ public abstract class GCParser {
LocParser.parseLoc(searchResult, coordinates);
} catch (Exception e) {
- Log.e("GCParser.parseSearch.CIDs: " + e.toString());
+ Log.e("GCParser.parseSearch.CIDs", e);
}
}
// get direction images
if (Settings.getLoadDirImg()) {
- final Set<cgCache> caches = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- for (cgCache cache : caches) {
+ final Set<Geocache> caches = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ for (Geocache cache : caches) {
if (cache.getCoords() == null && StringUtils.isNotEmpty(cache.getDirectionImg())) {
DirectionImage.getDrawable(cache.getGeocode(), cache.getDirectionImg());
}
@@ -315,18 +303,16 @@ public abstract class GCParser {
static SearchResult parseCache(final String page, final CancellableHandler handler) {
final SearchResult searchResult = parseCacheFromText(page, handler);
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
- final cgCache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
getExtraOnlineInfo(cache, page, handler);
- cache.setUpdated(System.currentTimeMillis());
- cache.setDetailedUpdate(cache.getUpdated());
- cache.setDetailed(true);
+ cache.setDetailedUpdatedNow();
if (CancellableHandler.isCancelled(handler)) {
return null;
}
// save full detailed caches
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache);
- cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
// update progress message so user knows we're still working. This is more of a place holder than
// actual indication of what the program is doing
@@ -345,7 +331,7 @@ public abstract class GCParser {
final SearchResult searchResult = new SearchResult();
- if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER)) {
+ if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || page.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
searchResult.setError(StatusCode.UNPUBLISHED_CACHE);
return searchResult;
}
@@ -361,7 +347,7 @@ public abstract class GCParser {
return searchResult;
}
- final cgCache cache = new cgCache();
+ final Geocache cache = new Geocache();
cache.setDisabled(page.contains(GCConstants.STRING_DISABLED));
cache.setArchived(page.contains(GCConstants.STRING_ARCHIVED));
@@ -383,9 +369,9 @@ public abstract class GCParser {
cache.setName(cacheName);
// owner real name
- cache.setOwnerUserId(URLDecoder.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
+ cache.setOwnerUserId(Network.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
- cache.setOwn(StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getUsername()));
+ cache.setUserModifiedCoords(false);
String tableInside = page;
@@ -401,13 +387,21 @@ public abstract class GCParser {
// cache terrain
String result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_TERRAIN, true, null);
if (result != null) {
- cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ try {
+ cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing terrain value", e);
+ }
}
// cache difficulty
result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_DIFFICULTY, true, null);
if (result != null) {
- cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ try {
+ cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing difficulty value", e);
+ }
}
// owner
@@ -432,10 +426,14 @@ public abstract class GCParser {
}
// favourite
- cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
+ try {
+ cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing favourite count", e);
+ }
// cache size
- cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id).toLowerCase()));
+ cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id)));
}
// cache found
@@ -459,18 +457,18 @@ public abstract class GCParser {
cache.setOnWatchlist(BaseUtils.matches(page, GCConstants.PATTERN_WATCHLIST));
// latitude and longitude. Can only be retrieved if user is logged in
- cache.setLatlon(BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON, true, cache.getLatlon()));
- if (StringUtils.isNotEmpty(cache.getLatlon())) {
+ String latlon = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON, true, "");
+ if (StringUtils.isNotEmpty(latlon)) {
try {
- cache.setCoords(new Geopoint(cache.getLatlon()));
+ cache.setCoords(new Geopoint(latlon));
cache.setReliableLatLon(true);
} catch (Geopoint.GeopointException e) {
- Log.w("GCParser.parseCache: Failed to parse cache coordinates: " + e.toString());
+ Log.w("GCParser.parseCache: Failed to parse cache coordinates", e);
}
}
// cache location
- cache.setLocation(BaseUtils.getMatch(page, GCConstants.PATTERN_LOCATION, true, cache.getLocation()));
+ cache.setLocation(BaseUtils.getMatch(page, GCConstants.PATTERN_LOCATION, true, ""));
// cache hint
String result = BaseUtils.getMatch(page, GCConstants.PATTERN_HINT, false, null);
@@ -488,7 +486,7 @@ public abstract class GCParser {
cache.setPersonalNote(BaseUtils.getMatch(page, GCConstants.PATTERN_PERSONALNOTE, true, cache.getPersonalNote()));
// cache short description
- cache.setShortdesc(BaseUtils.getMatch(page, GCConstants.PATTERN_SHORTDESC, true, cache.getShortdesc()));
+ cache.setShortDescription(BaseUtils.getMatch(page, GCConstants.PATTERN_SHORTDESC, true, ""));
// cache description
cache.setDescription(BaseUtils.getMatch(page, GCConstants.PATTERN_DESC, true, ""));
@@ -497,21 +495,21 @@ public abstract class GCParser {
try {
final String attributesPre = BaseUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null);
if (null != attributesPre) {
- final Matcher matcherAttributesInside = GCConstants.PATTERN_ATTRIBUTESINSIDE.matcher(attributesPre);
+ final MatcherWrapper matcherAttributesInside = new MatcherWrapper(GCConstants.PATTERN_ATTRIBUTESINSIDE, attributesPre);
final ArrayList<String> attributes = new ArrayList<String>();
while (matcherAttributesInside.find()) {
if (matcherAttributesInside.groupCount() > 1 && !matcherAttributesInside.group(2).equalsIgnoreCase("blank")) {
// by default, use the tooltip of the attribute
- String attribute = matcherAttributesInside.group(2).toLowerCase();
+ String attribute = matcherAttributesInside.group(2).toLowerCase(Locale.US);
// if the image name can be recognized, use the image name as attribute
- String imageName = matcherAttributesInside.group(1).trim();
- if (imageName.length() > 0) {
+ final String imageName = matcherAttributesInside.group(1).trim();
+ if (StringUtils.isNotEmpty(imageName)) {
int start = imageName.lastIndexOf('/');
int end = imageName.lastIndexOf('.');
if (start >= 0 && end >= 0) {
- attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase();
+ attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase(Locale.US);
}
}
attributes.add(attribute);
@@ -531,26 +529,22 @@ public abstract class GCParser {
}
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers);
- final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILER_IMAGE.matcher(page);
+ final MatcherWrapper matcherSpoilersInside = new MatcherWrapper(GCConstants.PATTERN_SPOILER_IMAGE, page);
while (matcherSpoilersInside.find()) {
// the original spoiler URL (include .../display/... contains a low-resolution image
// if we shorten the URL we get the original-resolution image
- //
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- String url = new String(matcherSpoilersInside.group(1).replace("/display", ""));
+ String url = matcherSpoilersInside.group(1).replace("/display", "");
String title = null;
if (matcherSpoilersInside.group(3) != null) {
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- title = new String(matcherSpoilersInside.group(3));
+ title = matcherSpoilersInside.group(3);
}
String description = null;
if (matcherSpoilersInside.group(4) != null) {
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- description = new String(matcherSpoilersInside.group(4));
+ description = matcherSpoilersInside.group(4);
}
- cache.addSpoiler(new cgImage(url, title, description));
+ cache.addSpoiler(new Image(url, title, description));
}
} catch (Exception e) {
// failed to parse cache spoilers
@@ -561,25 +555,23 @@ public abstract class GCParser {
try {
cache.setInventoryItems(0);
- final Matcher matcherInventory = GCConstants.PATTERN_INVENTORY.matcher(page);
+ final MatcherWrapper matcherInventory = new MatcherWrapper(GCConstants.PATTERN_INVENTORY, page);
if (matcherInventory.find()) {
if (cache.getInventory() == null) {
- cache.setInventory(new ArrayList<cgTrackable>());
+ cache.setInventory(new ArrayList<Trackable>());
}
if (matcherInventory.groupCount() > 1) {
final String inventoryPre = matcherInventory.group(2);
if (StringUtils.isNotBlank(inventoryPre)) {
- final Matcher matcherInventoryInside = GCConstants.PATTERN_INVENTORYINSIDE.matcher(inventoryPre);
+ final MatcherWrapper matcherInventoryInside = new MatcherWrapper(GCConstants.PATTERN_INVENTORYINSIDE, inventoryPre);
while (matcherInventoryInside.find()) {
if (matcherInventoryInside.groupCount() > 0) {
- final cgTrackable inventoryItem = new cgTrackable();
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- inventoryItem.setGuid(new String(matcherInventoryInside.group(1)));
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- inventoryItem.setName(new String(matcherInventoryInside.group(2)));
+ final Trackable inventoryItem = new Trackable();
+ inventoryItem.setGuid(matcherInventoryInside.group(1));
+ inventoryItem.setName(matcherInventoryInside.group(2));
cache.getInventory().add(inventoryItem);
cache.setInventoryItems(cache.getInventoryItems() + 1);
@@ -594,14 +586,12 @@ public abstract class GCParser {
}
// cache logs counts
- try
- {
+ try {
final String countlogs = BaseUtils.getMatch(page, GCConstants.PATTERN_COUNTLOGS, true, null);
if (null != countlogs) {
- final Matcher matcherLog = GCConstants.PATTERN_COUNTLOG.matcher(countlogs);
+ final MatcherWrapper matcherLog = new MatcherWrapper(GCConstants.PATTERN_COUNTLOG, countlogs);
- while (matcherLog.find())
- {
+ while (matcherLog.find()) {
String typeStr = matcherLog.group(1);
String countStr = matcherLog.group(2).replaceAll("[.,]", "");
@@ -612,21 +602,20 @@ public abstract class GCParser {
}
}
}
- } catch (Exception e)
- {
+ } catch (Exception e) {
// failed to parse logs
Log.w("GCParser.parseCache: Failed to parse cache log count");
}
// waypoints - reset collection
- cache.setWaypoints(Collections.<cgWaypoint> emptyList(), false);
+ cache.setWaypoints(Collections.<Waypoint> emptyList(), false);
// add waypoint for original coordinates in case of user-modified listing-coordinates
try {
final String originalCoords = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null);
if (null != originalCoords) {
- final cgWaypoint waypoint = new cgWaypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.WAYPOINT, false);
+ final Waypoint waypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
waypoint.setCoords(new Geopoint(originalCoords));
cache.addOrChangeWaypoint(waypoint, false);
cache.setUserModifiedCoords(true);
@@ -634,10 +623,7 @@ public abstract class GCParser {
} catch (Geopoint.GeopointException e) {
}
- int wpBegin;
- int wpEnd;
-
- wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
+ int wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
if (wpBegin != -1) { // parse waypoints
if (CancellableHandler.isCancelled(handler)) {
return null;
@@ -646,7 +632,7 @@ public abstract class GCParser {
String wpList = page.substring(wpBegin);
- wpEnd = wpList.indexOf("</p>");
+ int wpEnd = wpList.indexOf("</p>");
if (wpEnd > -1 && wpEnd <= wpList.length()) {
wpList = wpList.substring(0, wpEnd);
}
@@ -663,9 +649,8 @@ public abstract class GCParser {
final String[] wpItems = wpList.split("<tr");
- String[] wp;
for (int j = 1; j < wpItems.length; j++) {
- wp = wpItems[j].split("<td");
+ String[] wp = wpItems[j].split("<td");
// waypoint name
// res is null during the unit tests
@@ -674,7 +659,7 @@ public abstract class GCParser {
// waypoint type
final String resulttype = BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null);
- final cgWaypoint waypoint = new cgWaypoint(name, WaypointType.findById(resulttype), false);
+ final Waypoint waypoint = new Waypoint(name, WaypointType.findById(resulttype), false);
// waypoint prefix
waypoint.setPrefix(BaseUtils.getMatch(wp[4], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getPrefix(), false));
@@ -683,7 +668,7 @@ public abstract class GCParser {
waypoint.setLookup(BaseUtils.getMatch(wp[5], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getLookup(), false));
// waypoint latitude and logitude
- String latlon = Html.fromHtml(BaseUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim();
+ latlon = Html.fromHtml(BaseUtils.getMatch(wp[7], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, false, 2, "", false)).toString().trim();
if (!StringUtils.startsWith(latlon, "???")) {
waypoint.setLatlon(latlon);
waypoint.setCoords(new Geopoint(latlon));
@@ -756,12 +741,12 @@ public abstract class GCParser {
final SearchResult searchResult = parseSearch(url, page, showCaptcha);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
- Log.e("GCParser.searchByNextPage: No cache parsed");
+ Log.w("GCParser.searchByNextPage: No cache parsed");
return search;
}
// search results don't need to be filtered so load GCVote ratings here
- GCVote.loadRatings(new ArrayList<cgCache>(searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB)));
+ GCVote.loadRatings(new ArrayList<Geocache>(searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB)));
// save to application
search.setError(searchResult.getError());
@@ -896,13 +881,13 @@ public abstract class GCParser {
return null;
}
- public static cgTrackable searchTrackable(final String geocode, final String guid, final String id) {
+ public static Trackable searchTrackable(final String geocode, final String guid, final String id) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) {
Log.w("GCParser.searchTrackable: No geocode nor guid nor id given");
return null;
}
- cgTrackable trackable = new cgTrackable();
+ Trackable trackable = new Trackable();
final Parameters params = new Parameters();
if (StringUtils.isNotBlank(geocode)) {
@@ -923,43 +908,27 @@ public abstract class GCParser {
trackable = parseTrackable(page, geocode);
if (trackable == null) {
- Log.e("GCParser.searchTrackable: No trackable parsed");
+ Log.w("GCParser.searchTrackable: No trackable parsed");
return null;
}
return trackable;
}
- public static StatusCode postLog(final String geocode, final String cacheid, final String[] viewstates,
+ public static ImmutablePair<StatusCode, String> postLog(final String geocode, final String cacheid, final String[] viewstates,
final LogType logType, final int year, final int month, final int day,
final String log, final List<TrackableLog> trackables) {
if (Login.isEmpty(viewstates)) {
Log.e("GCParser.postLog: No viewstate given");
- return StatusCode.LOG_POST_ERROR;
+ return new ImmutablePair<StatusCode, String>(StatusCode.LOG_POST_ERROR, "");
}
if (StringUtils.isBlank(log)) {
Log.e("GCParser.postLog: No log text given");
- return StatusCode.NO_LOG_TEXT;
- }
-
- // fix log (non-Latin characters converted to HTML entities)
- final int logLen = log.length();
- final StringBuilder logUpdated = new StringBuilder();
-
- for (int i = 0; i < logLen; i++) {
- char c = log.charAt(i);
-
- if (c > 300) {
- logUpdated.append("&#");
- logUpdated.append(Integer.toString(c));
- logUpdated.append(';');
- } else {
- logUpdated.append(c);
- }
+ return new ImmutablePair<StatusCode, String>(StatusCode.NO_LOG_TEXT, "");
}
- final String logInfo = logUpdated.toString().replace("\n", "\r\n").trim(); // windows' eol and remove leading and trailing whitespaces
+ final String logInfo = HtmlUtils.convertNonLatinCharactersToHTML(log).replace("\n", "\r\n").trim(); // windows' eol and remove leading and trailing whitespaces
if (trackables != null) {
Log.i("Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + logInfo + "; trackables: " + trackables.size());
@@ -999,12 +968,12 @@ public abstract class GCParser {
String page = Login.postRequestLogged(uri, params);
if (!Login.getLoginStatus(page)) {
Log.e("GCParser.postLogTrackable: Can not log in geocaching");
- return StatusCode.NOT_LOGGED_IN;
+ return new ImmutablePair<StatusCode, String>(StatusCode.NOT_LOGGED_IN, "");
}
// maintenance, archived needs to be confirmed
- final Matcher matcher = GCConstants.PATTERN_MAINTENANCE.matcher(page);
+ final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_MAINTENANCE, page);
try {
if (matcher.find() && matcher.groupCount() > 0) {
@@ -1012,7 +981,7 @@ public abstract class GCParser {
if (Login.isEmpty(viewstatesConfirm)) {
Log.e("GCParser.postLog: No viewstate for confirm log");
- return StatusCode.LOG_POST_ERROR;
+ return new ImmutablePair<StatusCode, String>(StatusCode.LOG_POST_ERROR, "");
}
params.clear();
@@ -1048,17 +1017,17 @@ public abstract class GCParser {
page = Network.getResponseData(Network.postRequest(uri, params));
}
} catch (Exception e) {
- Log.e("GCParser.postLog.confim: " + e.toString());
+ Log.e("GCParser.postLog.confim", e);
}
try {
- final Matcher matcherOk = GCConstants.PATTERN_OK1.matcher(page);
+ final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK1, page);
if (matcherOk.find()) {
Log.i("Log successfully posted to cache #" + cacheid);
if (geocode != null) {
- cgeoapplication.getInstance().saveVisitDate(geocode);
+ cgData.saveVisitDate(geocode);
}
Login.getLoginStatus(page);
@@ -1066,14 +1035,71 @@ public abstract class GCParser {
if (Login.getActualCachesFound() >= 0) {
Login.setActualCachesFound(Login.getActualCachesFound() + 1);
}
- return StatusCode.NO_ERROR;
+
+ final String logID = BaseUtils.getMatch(page, GCConstants.PATTERN_LOG_IMAGE_UPLOAD, "");
+
+ return new ImmutablePair<StatusCode, String>(StatusCode.NO_ERROR, logID);
}
} catch (Exception e) {
- Log.e("GCParser.postLog.check: " + e.toString());
+ Log.e("GCParser.postLog.check", e);
}
Log.e("GCParser.postLog: Failed to post log because of unknown error");
- return StatusCode.LOG_POST_ERROR;
+ return new ImmutablePair<StatusCode, String>(StatusCode.LOG_POST_ERROR, "");
+ }
+
+ /**
+ * Upload an image to a log that has already been posted
+ *
+ * @param logId
+ * the ID of the log to upload the image to. Found on page returned when log is uploaded
+ * @param caption
+ * of the image; max 50 chars
+ * @param description
+ * of the image; max 250 chars
+ * @param imageUri
+ * the URI for the image to be uploaded
+ * @return status code to indicate success or failure
+ */
+ public static StatusCode 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));
+
+ 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 StatusCode.NOT_LOGGED_IN;
+ }
+ }
+
+ final String[] viewstates = Login.getViewstates(page);
+
+ final Parameters uploadParams = new Parameters(
+ "__EVENTTARGET", "",
+ "__EVENTARGUMENT", "",
+ "ctl00$ContentBody$ImageUploadControl1$uxFileCaption", HtmlUtils.convertNonLatinCharactersToHTML(caption),
+ "ctl00$ContentBody$ImageUploadControl1$uxFileDesc", HtmlUtils.convertNonLatinCharactersToHTML(description),
+ "ctl00$ContentBody$ImageUploadControl1$uxUpload", "Upload");
+ Login.putViewstates(uploadParams, viewstates);
+
+ final File image = new File(imageUri.getPath());
+ final String response = Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$ImageUploadControl1$uxFileUpload", "image/jpeg", image));
+
+ MatcherWrapper matcherOK = new MatcherWrapper(GCConstants.PATTERN_OK_IMAGEUPLOAD, response);
+
+ if (matcherOK.find()) {
+ Log.i("Logimage successfully uploaded.");
+
+ return StatusCode.NO_ERROR;
+ }
+ Log.e("GCParser.uploadLogIMage: Failed to upload image because of unknown error");
+
+ return StatusCode.LOGIMAGE_POST_ERROR;
}
public static StatusCode postLogTrackable(final String tbid, final String trackingCode, final String[] viewstates,
@@ -1090,7 +1116,7 @@ public abstract class GCParser {
Log.i("Trying to post log for trackable #" + trackingCode + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + log);
- final String logInfo = log.replace("\n", "\r\n"); // windows' eol
+ final String logInfo = HtmlUtils.convertNonLatinCharactersToHTML(log).replace("\n", "\r\n"); // windows' eol
final Calendar currentDate = Calendar.getInstance();
final Parameters params = new Parameters(
@@ -1122,13 +1148,13 @@ public abstract class GCParser {
try {
- final Matcher matcherOk = GCConstants.PATTERN_OK2.matcher(page);
+ final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK2, page);
if (matcherOk.find()) {
Log.i("Log successfully posted to trackable #" + trackingCode);
return StatusCode.NO_ERROR;
}
} catch (Exception e) {
- Log.e("GCParser.postLogTrackable.check: " + e.toString());
+ Log.e("GCParser.postLogTrackable.check", e);
}
Log.e("GCParser.postLogTrackable: Failed to post log because of unknown error");
@@ -1142,7 +1168,7 @@ public abstract class GCParser {
* the cache to add
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean addToWatchlist(final cgCache cache) {
+ static boolean addToWatchlist(final Geocache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?w=" + cache.getCacheId();
String page = Login.postRequestLogged(uri, null);
@@ -1168,7 +1194,7 @@ public abstract class GCParser {
* the cache to remove
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean removeFromWatchlist(final cgCache cache) {
+ static boolean removeFromWatchlist(final Geocache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?ds=1&action=rem&id=" + cache.getCacheId();
String page = Login.postRequestLogged(uri, null);
@@ -1211,15 +1237,17 @@ public abstract class GCParser {
/**
* Adds the cache to the favorites of the user.
*
+ * This must not be called from the UI thread.
+ *
* @param cache
* the cache to add
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean addToFavorites(final cgCache cache) {
+ static boolean addToFavorites(final Geocache cache) {
return changeFavorite(cache, true);
}
- private static boolean changeFavorite(final cgCache cache, final boolean add) {
+ private static boolean changeFavorite(final Geocache cache, final boolean add) {
final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
if (StringUtils.isEmpty(userToken)) {
@@ -1241,26 +1269,26 @@ public abstract class GCParser {
}
/**
- * Removes the cache from the Favorites
+ * Removes the cache from the favorites.
+ *
+ * This must not be called from the UI thread.
*
* @param cache
* the cache to remove
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean removeFromFavorites(final cgCache cache) {
+ static boolean removeFromFavorites(final Geocache cache) {
return changeFavorite(cache, false);
}
/**
- * Parse a trackable HTML description into a cgTrackable object
+ * Parse a trackable HTML description into a Trackable object
*
* @param page
* the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace}
- * @param app
- * if not null, the application to use to save the trackable
* @return the parsed trackable, or null if none could be parsed
*/
- static cgTrackable parseTrackable(final String page, final String possibleTrackingcode) {
+ static Trackable parseTrackable(final String page, final String possibleTrackingcode) {
if (StringUtils.isBlank(page)) {
Log.e("GCParser.parseTrackable: No page given");
return null;
@@ -1270,10 +1298,10 @@ public abstract class GCParser {
return null;
}
- final cgTrackable trackable = new cgTrackable();
+ final Trackable trackable = new Trackable();
// trackable geocode
- trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase());
+ trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()));
// trackable id
trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid()));
@@ -1291,7 +1319,7 @@ public abstract class GCParser {
// trackable owner name
try {
- final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page);
+ final MatcherWrapper matcherOwner = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_OWNER, page);
if (matcherOwner.find() && matcherOwner.groupCount() > 0) {
trackable.setOwnerGuid(matcherOwner.group(1));
trackable.setOwner(matcherOwner.group(2).trim());
@@ -1306,26 +1334,26 @@ public abstract class GCParser {
// trackable spotted
try {
- final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page);
+ final MatcherWrapper matcherSpottedCache = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE, page);
if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) {
trackable.setSpottedGuid(matcherSpottedCache.group(1));
trackable.setSpottedName(matcherSpottedCache.group(2).trim());
- trackable.setSpottedType(cgTrackable.SPOTTED_CACHE);
+ trackable.setSpottedType(Trackable.SPOTTED_CACHE);
}
- final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page);
+ final MatcherWrapper matcherSpottedUser = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER, page);
if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) {
trackable.setSpottedGuid(matcherSpottedUser.group(1));
trackable.setSpottedName(matcherSpottedUser.group(2).trim());
- trackable.setSpottedType(cgTrackable.SPOTTED_USER);
+ trackable.setSpottedType(Trackable.SPOTTED_USER);
}
if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) {
- trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN);
+ trackable.setSpottedType(Trackable.SPOTTED_UNKNOWN);
}
if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) {
- trackable.setSpottedType(cgTrackable.SPOTTED_OWNER);
+ trackable.setSpottedType(Trackable.SPOTTED_OWNER);
}
} catch (Exception e) {
// failed to parse trackable last known place
@@ -1356,7 +1384,7 @@ public abstract class GCParser {
// trackable details & image
try {
- final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page);
+ final MatcherWrapper matcherDetailsImage = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE, page);
if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) {
final String image = StringUtils.trim(matcherDetailsImage.group(3));
final String details = StringUtils.trim(matcherDetailsImage.group(4));
@@ -1375,7 +1403,7 @@ public abstract class GCParser {
// trackable logs
try {
- final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page);
+ final MatcherWrapper matcherLogs = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG, page);
/*
* 1. Type (image)
* 2. Date
@@ -1404,13 +1432,14 @@ public abstract class GCParser {
}
// Apply the pattern for images in a trackable log entry against each full log (group(0))
- final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0));
+ final String logEntry = matcherLogs.group(0);
+ final MatcherWrapper matcherLogImages = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG_IMAGES, logEntry);
/*
* 1. Image URL
* 2. Image title
*/
while (matcherLogImages.find()) {
- final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2));
+ final Image logImage = new Image(matcherLogImages.group(1), matcherLogImages.group(2));
logDone.addLogImage(logImage);
}
@@ -1418,7 +1447,7 @@ public abstract class GCParser {
}
} catch (Exception e) {
// failed to parse logs
- Log.w("GCParser.parseCache: Failed to parse cache logs" + e.toString());
+ Log.w("GCParser.parseCache: Failed to parse cache logs", e);
}
// tracking code
@@ -1427,7 +1456,7 @@ public abstract class GCParser {
}
if (cgeoapplication.getInstance() != null) {
- cgeoapplication.getInstance().saveTrackable(trackable);
+ cgData.saveTrackable(trackable);
}
return trackable;
@@ -1450,11 +1479,11 @@ public abstract class GCParser {
* @param friends
* retrieve friend logs
*/
- private static List<LogEntry> loadLogsFromDetails(final String page, final cgCache cache, final boolean friends, final boolean getDataFromPage) {
+ private static List<LogEntry> loadLogsFromDetails(final String page, final Geocache cache, final boolean friends, final boolean getDataFromPage) {
String rawResponse;
if (!getDataFromPage) {
- final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN.matcher(page);
+ final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page);
if (!userTokenMatcher.find()) {
Log.e("GCParser.loadLogsFromDetails: unable to extract userToken");
return null;
@@ -1532,7 +1561,7 @@ public abstract class GCParser {
final JSONObject image = images.getJSONObject(i);
String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName");
String title = image.getString("Name");
- final cgImage logImage = new cgImage(url, title);
+ final Image logImage = new Image(url, title);
logDone.addLogImage(logImage);
}
@@ -1553,7 +1582,7 @@ public abstract class GCParser {
final List<LogType> types = new ArrayList<LogType>();
- final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page);
+ final MatcherWrapper typeBoxMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPEBOX, page);
String typesText = null;
if (typeBoxMatcher.find()) {
if (typeBoxMatcher.groupCount() > 0) {
@@ -1563,13 +1592,16 @@ public abstract class GCParser {
if (typesText != null) {
- final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText);
+ final MatcherWrapper typeMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPE2, typesText);
while (typeMatcher.find()) {
if (typeMatcher.groupCount() > 1) {
- final int type = Integer.parseInt(typeMatcher.group(2));
-
- if (type > 0) {
- types.add(LogType.getById(type));
+ try {
+ int type = Integer.parseInt(typeMatcher.group(2));
+ if (type > 0) {
+ types.add(LogType.getById(type));
+ }
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing log types", e);
}
}
}
@@ -1598,7 +1630,7 @@ public abstract class GCParser {
final List<TrackableLog> trackableLogs = new ArrayList<TrackableLog>();
- final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page);
+ final MatcherWrapper trackableMatcher = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE, page);
while (trackableMatcher.find()) {
if (trackableMatcher.groupCount() > 0) {
@@ -1634,7 +1666,7 @@ public abstract class GCParser {
params.put("tx", cacheType.guid);
}
- private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) {
+ private static void getExtraOnlineInfo(final Geocache cache, final String page, final CancellableHandler handler) {
if (CancellableHandler.isCancelled(handler)) {
return;
}
@@ -1642,7 +1674,7 @@ public abstract class GCParser {
//cache.setLogs(loadLogsFromDetails(page, cache, false));
if (Settings.isFriendLogsWanted()) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- LazyInitializedList<LogEntry> allLogs = cache.getLogs();
+ List<LogEntry> allLogs = cache.getLogs();
List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false);
if (friendLogs != null) {
for (LogEntry log : friendLogs) {
@@ -1679,4 +1711,48 @@ public abstract class GCParser {
}
}
+ public static boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ return editModifiedCoordinates(cache, wpt);
+ }
+
+ public static boolean deleteModifiedCoordinates(Geocache cache) {
+ return editModifiedCoordinates(cache, null);
+ }
+
+ public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
+ final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ if (StringUtils.isEmpty(userToken)) {
+ return false;
+ }
+
+ try {
+ JSONObject jo;
+ if (wpt != null) {
+ jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken)
+ .put("data", new JSONObject()
+ .put("lat", wpt.getLatitudeE6() / 1E6)
+ .put("lng", wpt.getLongitudeE6() / 1E6))));
+ } else {
+ jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken)));
+ }
+
+ final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate";
+
+ final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
+ HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
+ Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
+
+ if (response != null && response.getStatusLine().getStatusCode() == 200) {
+ Log.i("GCParser.editModifiedCoordinates - edited on GC.com");
+ return true;
+ }
+
+ } catch (JSONException e) {
+ Log.e("Unknown exception with json wrap code", e);
+ }
+ Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords");
+ return false;
+ }
+
}