package carnero.cgeo.original.libs;
import carnero.cgeo.original.models.TrackableLog;
import carnero.cgeo.original.models.User;
import carnero.cgeo.original.models.Spoiler;
import carnero.cgeo.original.models.Trackable;
import carnero.cgeo.original.models.Response;
import carnero.cgeo.original.models.Search;
import carnero.cgeo.original.R;
import carnero.cgeo.original.main;
import carnero.cgeo.original.models.Waypoint;
import carnero.cgeo.original.models.Cache;
import carnero.cgeo.original.models.CacheLog;
import carnero.cgeo.original.models.Coord;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.util.Map;
import java.util.Calendar;
import java.util.Locale;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
import android.text.Spannable;
import android.text.style.StrikethroughSpan;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.google.android.apps.analytics.GoogleAnalyticsTracker;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.json.JSONArray;
import org.json.JSONObject;
public class Base {
public Context context = null;
private App app = null;
private Settings settings = null;
private SharedPreferences prefs = null;
private Resources res = null;
public static HashMap<String, String> cacheTypes = new HashMap<String, String>();
public static HashMap<String, String> cacheTypesInv = new HashMap<String, String>();
public static HashMap<String, String> cacheIDs = new HashMap<String, String>();
public static HashMap<String, String> cacheIDsChoices = new HashMap<String, String>();
public static HashMap<String, String> waypointTypes = new HashMap<String, String>();
public static HashMap<String, Integer> logTypes = new HashMap<String, Integer>();
public static HashMap<String, Integer> logTypes0 = new HashMap<String, Integer>();
public static HashMap<Integer, String> logTypes1 = new HashMap<Integer, String>();
public static HashMap<Integer, String> logTypes2 = new HashMap<Integer, String>();
public static HashMap<Integer, String> logTypesTrackable = new HashMap<Integer, String>();
public static HashMap<Integer, String> logTypesTrackableAction = new HashMap<Integer, String>();
public static HashMap<Integer, String> errorRetrieve = new HashMap<Integer, String>();
public static SimpleDateFormat dateIn = new SimpleDateFormat("MM/dd/yyyy");
public static SimpleDateFormat dateEvIn = new SimpleDateFormat("dd MMMMM yyyy", Locale.ENGLISH); // 28 March 2009
public static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
public static SimpleDateFormat dateTbIn2 = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009
public static SimpleDateFormat dateSqlIn = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 2010-07-25 14:44:01
public static SimpleDateFormat dateGPXIn = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // 2010-04-20T07:00:00Z
public static SimpleDateFormat dateLogIn = new SimpleDateFormat("dd/MM/yyyy"); // 30/09/2011
public static DateFormat dateOut = DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault());
public static DateFormat timeOut = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault());
public static DateFormat dateOutShort = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
private HashMap<String, String> cookies = new HashMap<String, String>();
private final String passMatch = "[/\\?&]*[Pp]ass(word)?=[^&^#^$]+";
private final Pattern patternLoggedIn = Pattern.compile("<span class=\"Success\">You are logged in as[^<]*<strong[^>]*>([^<]+)</strong>[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private final Pattern patternLogged2In = Pattern.compile("<strong>[^\\w]*Hello,[^<]*<a[^>]+>([^<]+)</a>[^<]*</strong>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private final Pattern patternViewstate = Pattern.compile("id=\"__VIEWSTATE\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private final Pattern patternViewstate1 = Pattern.compile("id=\"__VIEWSTATE1\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
public static final double kmInMiles = 1 / 1.609344;
public static final double deg2rad = Math.PI / 180;
public static final double rad2deg = 180 / Math.PI;
public static final float erad = 6371.0f;
public static final int mapAppAny = 0;
public static final int mapAppLocus = 1;
public static final int mapAppRmaps = 2;
public String version = null;
private String idBrowser = "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4";
final private static HashMap<String, Integer> gcIcons = new HashMap<String, Integer>();
final private static HashMap<String, Integer> wpIcons = new HashMap<String, Integer>();
public static final int LOG_FOUND_IT = 2;
public static final int LOG_DIDNT_FIND_IT = 3;
public static final int LOG_NOTE = 4;
public static final int LOG_PUBLISH_LISTING = 1003; // unknown ID; used number doesn't match any GC.com's ID
public static final int LOG_ENABLE_LISTING = 23;
public static final int LOG_ARCHIVE = 5;
public static final int LOG_TEMP_DISABLE_LISTING = 22;
public static final int LOG_NEEDS_ARCHIVE = 7;
public static final int LOG_WILL_ATTEND = 9;
public static final int LOG_ATTENDED = 10;
public static final int LOG_RETRIEVED_IT = 13;
public static final int LOG_PLACED_IT = 14;
public static final int LOG_GRABBED_IT = 19;
public static final int LOG_NEEDS_MAINTENANCE = 45;
public static final int LOG_OWNER_MAINTENANCE = 46;
public static final int LOG_UPDATE_COORDINATES = 47;
public static final int LOG_DISCOVERED_IT = 48;
public static final int LOG_POST_REVIEWER_NOTE = 18;
public static final int LOG_VISIT = 1001; // unknown ID; used number doesn't match any GC.com's ID
public static final int LOG_WEBCAM_PHOTO_TAKEN = 11;
public static final int LOG_ANNOUNCEMENT = 74;
public Base(App appIn, Settings settingsIn, SharedPreferences prefsIn) {
context = appIn.getBaseContext();
res = appIn.getBaseContext().getResources();
// cache types
cacheTypes.put("traditional cache", "traditional");
cacheTypes.put("multi-cache", "multi");
cacheTypes.put("unknown cache", "mystery");
cacheTypes.put("letterbox hybrid", "letterbox");
cacheTypes.put("event cache", "event");
cacheTypes.put("mega-event cache", "mega");
cacheTypes.put("earthcache", "earth");
cacheTypes.put("cache in trash out event", "cito");
cacheTypes.put("webcam cache", "webcam");
cacheTypes.put("virtual cache", "virtual");
cacheTypes.put("wherigo cache", "wherigo");
cacheTypes.put("lost & found", "lostfound");
cacheTypes.put("project ape cache", "ape");
cacheTypes.put("groundspeak hq", "gchq");
cacheTypes.put("gps cache exhibit", "gps");
// cache types inverted
cacheTypesInv.put("traditional", res.getString(R.string.traditional));
cacheTypesInv.put("multi", res.getString(R.string.multi));
cacheTypesInv.put("mystery", res.getString(R.string.mystery));
cacheTypesInv.put("letterbox", res.getString(R.string.letterbox));
cacheTypesInv.put("event", res.getString(R.string.event));
cacheTypesInv.put("mega", res.getString(R.string.mega));
cacheTypesInv.put("earth", res.getString(R.string.earth));
cacheTypesInv.put("cito", res.getString(R.string.cito));
cacheTypesInv.put("webcam", res.getString(R.string.webcam));
cacheTypesInv.put("virtual", res.getString(R.string.virtual));
cacheTypesInv.put("wherigo", res.getString(R.string.wherigo));
cacheTypesInv.put("lostfound", res.getString(R.string.lostfound));
cacheTypesInv.put("ape", res.getString(R.string.ape));
cacheTypesInv.put("gchq", res.getString(R.string.gchq));
cacheTypesInv.put("gps", res.getString(R.string.gps));
// cache ids
cacheIDs.put("all", "9a79e6ce-3344-409c-bbe9-496530baf758"); // hard-coded also in Settings
cacheIDs.put("traditional", "32bc9333-5e52-4957-b0f6-5a2c8fc7b257");
cacheIDs.put("multi", "a5f6d0ad-d2f2-4011-8c14-940a9ebf3c74");
cacheIDs.put("mystery", "40861821-1835-4e11-b666-8d41064d03fe");
cacheIDs.put("letterbox", "4bdd8fb2-d7bc-453f-a9c5-968563b15d24");
cacheIDs.put("event", "69eb8534-b718-4b35-ae3c-a856a55b0874");
cacheIDs.put("mega-event", "69eb8535-b718-4b35-ae3c-a856a55b0874");
cacheIDs.put("earth", "c66f5cf3-9523-4549-b8dd-759cd2f18db8");
cacheIDs.put("cito", "57150806-bc1a-42d6-9cf0-538d171a2d22");
cacheIDs.put("webcam", "31d2ae3c-c358-4b5f-8dcd-2185bf472d3d");
cacheIDs.put("virtual", "294d4360-ac86-4c83-84dd-8113ef678d7e");
cacheIDs.put("wherigo", "0544fa55-772d-4e5c-96a9-36a51ebcf5c9");
cacheIDs.put("lostfound", "3ea6533d-bb52-42fe-b2d2-79a3424d4728");
cacheIDs.put("ape", "2555690d-b2bc-4b55-b5ac-0cb704c0b768");
cacheIDs.put("gchq", "416f2494-dc17-4b6a-9bab-1a29dd292d8c");
cacheIDs.put("gps", "72e69af2-7986-4990-afd9-bc16cbbb4ce3");
// cache choices
cacheIDsChoices.put(res.getString(R.string.all), cacheIDs.get("all"));
cacheIDsChoices.put(res.getString(R.string.traditional), cacheIDs.get("traditional"));
cacheIDsChoices.put(res.getString(R.string.multi), cacheIDs.get("multi"));
cacheIDsChoices.put(res.getString(R.string.mystery), cacheIDs.get("mystery"));
cacheIDsChoices.put(res.getString(R.string.letterbox), cacheIDs.get("letterbox"));
cacheIDsChoices.put(res.getString(R.string.event), cacheIDs.get("event"));
cacheIDsChoices.put(res.getString(R.string.mega), cacheIDs.get("mega"));
cacheIDsChoices.put(res.getString(R.string.earth), cacheIDs.get("earth"));
cacheIDsChoices.put(res.getString(R.string.cito), cacheIDs.get("cito"));
cacheIDsChoices.put(res.getString(R.string.webcam), cacheIDs.get("webcam"));
cacheIDsChoices.put(res.getString(R.string.virtual), cacheIDs.get("virtual"));
cacheIDsChoices.put(res.getString(R.string.wherigo), cacheIDs.get("whereigo"));
cacheIDsChoices.put(res.getString(R.string.lostfound), cacheIDs.get("lostfound"));
cacheIDsChoices.put(res.getString(R.string.ape), cacheIDs.get("ape"));
cacheIDsChoices.put(res.getString(R.string.gchq), cacheIDs.get("gchq"));
cacheIDsChoices.put(res.getString(R.string.gps), cacheIDs.get("gps"));
// waypoint types
waypointTypes.put("flag", res.getString(R.string.wp_final));
waypointTypes.put("stage", res.getString(R.string.wp_stage));
waypointTypes.put("puzzle", res.getString(R.string.wp_puzzle));
waypointTypes.put("pkg", res.getString(R.string.wp_pkg));
waypointTypes.put("trailhead", res.getString(R.string.wp_trailhead));
waypointTypes.put("waypoint", res.getString(R.string.wp_waypoint));
// log types
logTypes.put("icon_smile", LOG_FOUND_IT);
logTypes.put("icon_sad", LOG_DIDNT_FIND_IT);
logTypes.put("icon_note", LOG_NOTE);
logTypes.put("icon_greenlight", LOG_PUBLISH_LISTING);
logTypes.put("icon_enabled", LOG_ENABLE_LISTING);
logTypes.put("traffic_cone", LOG_ARCHIVE);
logTypes.put("icon_disabled", LOG_TEMP_DISABLE_LISTING);
logTypes.put("icon_remove", LOG_NEEDS_ARCHIVE);
logTypes.put("icon_rsvp", LOG_WILL_ATTEND);
logTypes.put("icon_attended", LOG_ATTENDED);
logTypes.put("picked_up", LOG_RETRIEVED_IT);
logTypes.put("dropped_off", LOG_PLACED_IT);
logTypes.put("transfer", LOG_GRABBED_IT);
logTypes.put("icon_needsmaint", LOG_NEEDS_MAINTENANCE);
logTypes.put("icon_maint", LOG_OWNER_MAINTENANCE);
logTypes.put("coord_update", LOG_UPDATE_COORDINATES);
logTypes.put("icon_discovered", LOG_DISCOVERED_IT);
logTypes.put("big_smile", LOG_POST_REVIEWER_NOTE);
logTypes.put("icon_visited", LOG_VISIT); // unknown ID; used number doesn't match any GC.com's ID
logTypes.put("icon_camera", LOG_WEBCAM_PHOTO_TAKEN); // unknown ID; used number doesn't match any GC.com's ID
logTypes.put("icon_announcement", LOG_ANNOUNCEMENT); // unknown ID; used number doesn't match any GC.com's ID
logTypes0.put("found it", LOG_FOUND_IT);
logTypes0.put("didn't find it", LOG_DIDNT_FIND_IT);
logTypes0.put("write note", LOG_NOTE);
logTypes0.put("publish listing", LOG_PUBLISH_LISTING);
logTypes0.put("enable listing", LOG_ENABLE_LISTING);
logTypes0.put("archive", LOG_ARCHIVE);
logTypes0.put("temporarily disable listing", LOG_TEMP_DISABLE_LISTING);
logTypes0.put("needs archived", LOG_NEEDS_ARCHIVE);
logTypes0.put("will attend", LOG_WILL_ATTEND);
logTypes0.put("attended", LOG_ATTENDED);
logTypes0.put("retrieved it", LOG_RETRIEVED_IT);
logTypes0.put("placed it", LOG_PLACED_IT);
logTypes0.put("grabbed it", LOG_GRABBED_IT);
logTypes0.put("needs maintenance", LOG_NEEDS_MAINTENANCE);
logTypes0.put("owner maintenance", LOG_OWNER_MAINTENANCE);
logTypes0.put("update coordinates", LOG_UPDATE_COORDINATES);
logTypes0.put("discovered it", LOG_DISCOVERED_IT);
logTypes0.put("post reviewer note", LOG_POST_REVIEWER_NOTE);
logTypes0.put("visit", LOG_VISIT); // unknown ID; used number doesn't match any GC.com's ID
logTypes0.put("webcam photo taken", LOG_WEBCAM_PHOTO_TAKEN); // unknown ID; used number doesn't match any GC.com's ID
logTypes0.put("announcement", LOG_ANNOUNCEMENT); // unknown ID; used number doesn't match any GC.com's ID
logTypes1.put(LOG_FOUND_IT, res.getString(R.string.log_found));
logTypes1.put(LOG_DIDNT_FIND_IT, res.getString(R.string.log_dnf));
logTypes1.put(LOG_NOTE, res.getString(R.string.log_note));
logTypes1.put(LOG_PUBLISH_LISTING, res.getString(R.string.log_published));
logTypes1.put(LOG_ENABLE_LISTING, res.getString(R.string.log_enabled));
logTypes1.put(LOG_ARCHIVE, res.getString(R.string.log_archived));
logTypes1.put(LOG_TEMP_DISABLE_LISTING, res.getString(R.string.log_disabled));
logTypes1.put(LOG_NEEDS_ARCHIVE, res.getString(R.string.log_needs_archived));
logTypes1.put(LOG_WILL_ATTEND, res.getString(R.string.log_attend));
logTypes1.put(LOG_ATTENDED, res.getString(R.string.log_attended));
logTypes1.put(LOG_RETRIEVED_IT, res.getString(R.string.log_retrieved));
logTypes1.put(LOG_PLACED_IT, res.getString(R.string.log_placed));
logTypes1.put(LOG_GRABBED_IT, res.getString(R.string.log_grabbed));
logTypes1.put(LOG_NEEDS_MAINTENANCE, res.getString(R.string.log_maintenance_needed));
logTypes1.put(LOG_OWNER_MAINTENANCE, res.getString(R.string.log_maintained));
logTypes1.put(LOG_UPDATE_COORDINATES, res.getString(R.string.log_update));
logTypes1.put(LOG_DISCOVERED_IT, res.getString(R.string.log_discovered));
logTypes1.put(LOG_POST_REVIEWER_NOTE, res.getString(R.string.log_reviewed));
logTypes1.put(LOG_VISIT, res.getString(R.string.log_taken));
logTypes1.put(LOG_WEBCAM_PHOTO_TAKEN, res.getString(R.string.log_webcam));
logTypes1.put(LOG_ANNOUNCEMENT, res.getString(R.string.log_announcement));
logTypes2.put(LOG_FOUND_IT, res.getString(R.string.log_found)); // traditional, multi, unknown, earth, wherigo, virtual, letterbox
logTypes2.put(LOG_DIDNT_FIND_IT, res.getString(R.string.log_dnf)); // traditional, multi, unknown, earth, wherigo, virtual, letterbox, webcam
logTypes2.put(LOG_NOTE, res.getString(R.string.log_note)); // traditional, multi, unknown, earth, wherigo, virtual, event, letterbox, webcam, trackable
logTypes2.put(LOG_PUBLISH_LISTING, res.getString(R.string.log_published)); // X
logTypes2.put(LOG_ENABLE_LISTING, res.getString(R.string.log_enabled)); // owner
logTypes2.put(LOG_ARCHIVE, res.getString(R.string.log_archived)); // traditional, multi, unknown, earth, event, wherigo, virtual, letterbox, webcam
logTypes2.put(LOG_TEMP_DISABLE_LISTING, res.getString(R.string.log_disabled)); // owner
logTypes2.put(LOG_NEEDS_ARCHIVE, res.getString(R.string.log_needs_archived)); // traditional, multi, unknown, earth, event, wherigo, virtual, letterbox, webcam
logTypes2.put(LOG_WILL_ATTEND, res.getString(R.string.log_attend)); // event
logTypes2.put(LOG_ATTENDED, res.getString(R.string.log_attended)); // event
logTypes2.put(LOG_WEBCAM_PHOTO_TAKEN, res.getString(R.string.log_webcam)); // webcam
logTypes2.put(LOG_RETRIEVED_IT, res.getString(R.string.log_retrieved)); //trackable
logTypes2.put(LOG_GRABBED_IT, res.getString(R.string.log_grabbed)); //trackable
logTypes2.put(LOG_NEEDS_MAINTENANCE, res.getString(R.string.log_maintenance_needed)); // traditional, unknown, multi, wherigo, virtual, letterbox, webcam
logTypes2.put(LOG_OWNER_MAINTENANCE, res.getString(R.string.log_maintained)); // owner
logTypes2.put(LOG_DISCOVERED_IT, res.getString(R.string.log_discovered)); //trackable
logTypes2.put(LOG_POST_REVIEWER_NOTE, res.getString(R.string.log_reviewed)); // X
logTypes2.put(LOG_ANNOUNCEMENT, res.getString(R.string.log_announcement)); // X
// trackables for logs
logTypesTrackable.put(0, res.getString(R.string.log_tb_nothing)); // do nothing
logTypesTrackable.put(1, res.getString(R.string.log_tb_visit)); // visit cache
logTypesTrackable.put(2, res.getString(R.string.log_tb_drop)); // drop here
logTypesTrackableAction.put(0, ""); // do nothing
logTypesTrackableAction.put(1, "_Visited"); // visit cache
logTypesTrackableAction.put(2, "_DroppedOff"); // drop here
// retrieving errors (because of ____ )
errorRetrieve.put(1, res.getString(R.string.err_none));
errorRetrieve.put(0, res.getString(R.string.err_start));
errorRetrieve.put(-1, res.getString(R.string.err_parse));
errorRetrieve.put(-2, res.getString(R.string.err_server));
errorRetrieve.put(-3, res.getString(R.string.err_login));
errorRetrieve.put(-4, res.getString(R.string.err_unknown));
errorRetrieve.put(-5, res.getString(R.string.err_comm));
errorRetrieve.put(-6, res.getString(R.string.err_wrong));
errorRetrieve.put(-7, res.getString(R.string.err_license));
// init
app = appIn;
settings = settingsIn;
prefs = prefsIn;
try {
PackageManager manager = app.getPackageManager();
PackageInfo info = manager.getPackageInfo(app.getPackageName(), 0);
version = info.versionName;
} catch (Exception e) {
// nothing
}
if (settings.asBrowser == 1) {
final long rndBrowser = Math.round(Math.random() * 6);
if (rndBrowser == 0) {
idBrowser = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.322.2 Safari/533.1";
} else if (rndBrowser == 1) {
idBrowser = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDC)";
} else if (rndBrowser == 2) {
idBrowser = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3";
} else if (rndBrowser == 3) {
idBrowser = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10";
} else if (rndBrowser == 4) {
idBrowser = "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20";
} else if (rndBrowser == 5) {
idBrowser = "Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2";
} else if (rndBrowser == 6) {
idBrowser = "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4";
} else {
idBrowser = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.307.11 Safari/532.9";
}
}
}
public String findViewstate(String page, int index) {
String viewstate = null;
if (index == 0) {
final Matcher matcherViewstate = patternViewstate.matcher(page);
while (matcherViewstate.find()) {
if (matcherViewstate.groupCount() > 0) {
viewstate = matcherViewstate.group(1);
}
}
} else if (index == 1) {
final Matcher matcherViewstate = patternViewstate1.matcher(page);
while (matcherViewstate.find()) {
if (matcherViewstate.groupCount() > 0) {
viewstate = matcherViewstate.group(1);
}
}
}
return viewstate;
}
public class loginThread extends Thread {
@Override
public void run() {
login();
}
}
public int login() {
final String host = "www.geocaching.com";
final String path = "/login/default.aspx?redir=/default.aspx?";
Response loginResponse = null;
String loginData = null;
String viewstate = null;
String viewstate1 = null;
final HashMap<String, String> loginStart = settings.getLogin();
if (loginStart == null) {
return -3; // no login information stored
}
loginResponse = request(true, host, path, "GET", new HashMap<String, String>(), false, false, false);
loginData = loginResponse.getData();
if (loginData != null && loginData.length() > 0) {
if (checkLogin(loginData) == true) {
Log.i(Settings.tag, "Already logged in Geocaching.com as " + loginStart.get("username"));
switchToEnglish(viewstate, viewstate1);
return 1; // logged in
}
viewstate = findViewstate(loginData, 0);
viewstate1 = findViewstate(loginData, 1);
if (viewstate == null || viewstate.length() == 0) {
Log.e(Settings.tag, "cgeoBase.login: Failed to find viewstate");
return -1; // no viewstate
}
} else {
Log.e(Settings.tag, "cgeoBase.login: Failed to retrieve login page (1st)");
return -2; // no loginpage
}
final HashMap<String, String> login = settings.getLogin();
final HashMap<String, String> params = new HashMap<String, String>();
if (login == null || login.get("username") == null || login.get("username").length() == 0 || login.get("password") == null || login.get("password").length() == 0) {
Log.e(Settings.tag, "cgeoBase.login: No login information stored");
return -3;
}
settings.deleteCookies();
params.put("__EVENTTARGET", "");
params.put("__EVENTARGUMENT", "");
params.put("__VIEWSTATE", viewstate);
if (viewstate1 != null) {
params.put("__VIEWSTATE1", viewstate1);
params.put("__VIEWSTATEFIELDCOUNT", "2");
}
params.put("ctl00$tbUsername", login.get("username"));
params.put("ctl00$tbPassword", login.get("password"));
params.put("ctl00$cbRememberMe", "on");
params.put("ctl00$btnSignIn", "Sign In");
loginResponse = request(true, host, path, "POST", params, false, false, false);
loginData = loginResponse.getData();
if (loginData != null && loginData.length() > 0) {
if (checkLogin(loginData) == true) {
Log.i(Settings.tag, "Successfully logged in Geocaching.com as " + login.get("username"));
switchToEnglish(findViewstate(loginData, 0), findViewstate(loginData, 1));
return 1; // logged in
} else {
if (loginData.indexOf("Your username/password combination does not match.") != -1) {
Log.i(Settings.tag, "Failed to log in Geocaching.com as " + login.get("username") + " because of wrong username/password");
return -6; // wrong login
} else {
Log.i(Settings.tag, "Failed to log in Geocaching.com as " + login.get("username") + " for some unknown reason");
return -4; // can't login
}
}
} else {
Log.e(Settings.tag, "cgeoBase.login: Failed to retrieve login page (2nd)");
return -5; // no login page
}
}
public Boolean checkLogin(String page) {
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.checkLogin: No page given");
return false;
}
// on every page
final Matcher matcherLogged2In = patternLogged2In.matcher(page);
while (matcherLogged2In.find()) {
return true;
}
// after login
final Matcher matcherLoggedIn = patternLoggedIn.matcher(page);
while (matcherLoggedIn.find()) {
return true;
}
return false;
}
public String switchToEnglish(String viewstate, String viewstate1) {
final String host = "www.geocaching.com";
final String path = "/default.aspx";
final HashMap<String, String> params = new HashMap<String, String>();
if (viewstate != null) {
params.put("__VIEWSTATE", viewstate);
}
if (viewstate1 != null) {
params.put("__VIEWSTATE1", viewstate1);
params.put("__VIEWSTATEFIELDCOUNT", "2");
}
params.put("__EVENTTARGET", "ctl00$uxLocaleList$uxLocaleList$ctl00$uxLocaleItem"); // switch to english
params.put("__EVENTARGUMENT", "");
return request(false, host, path, "POST", params, false, false, false).getData();
}
public CacheWrap parseSearch(SearchThread thread, String url, String page, boolean showCaptcha) {
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.parseSearch: No page given");
return null;
}
final CacheWrap caches = new CacheWrap();
final ArrayList<String> cids = new ArrayList<String>();
final ArrayList<String> guids = new ArrayList<String>();
String recaptchaChallenge = null;
String recaptchaText = null;
caches.url = url;
final Pattern patternCacheType = Pattern.compile("<td class=\"Merge\">[^<]*<a href=\"[^\"]*/seek/cache_details\\.aspx\\?guid=[^\"]+\"[^>]+>[^<]*<img src=\"[^\"]*/images/wpttypes/[^\\.]+\\.gif\" alt=\"([^\"]+)\" title=\"[^\"]+\"[^>]*>[^<]*</a>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternGuidAndDisabled = Pattern.compile("<img src=\"[^\"]*/images/wpttypes/[^>]*>[^<]*</a></td><td class=\"Merge\">[^<]*<a href=\"[^\"]*/seek/cache_details\\.aspx\\?guid=([a-z0-9\\-]+)\" class=\"lnk([^\"]*)\">([^<]*<span>)?([^<]*)(</span>[^<]*)?</a>[^<]+<br />([^<]*)<span[^>]+>([^<]*)</span>([^<]*<img[^>]+>)?[^<]*<br />[^<]*</td>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternTbs = Pattern.compile("<a id=\"ctl00_ContentBody_dlResults_ctl[0-9]+_uxTravelBugList\" class=\"tblist\" data-tbcount=\"([0-9]+)\" data-id=\"[^\"]*\"[^>]*>(.*)</a>", Pattern.CASE_INSENSITIVE);
final Pattern patternTbsInside = Pattern.compile("(<img src=\"[^\"]+\" alt=\"([^\"]+)\" title=\"[^\"]*\" />[^<]*)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternDirection = Pattern.compile("<img id=\"ctl00_ContentBody_dlResults_ctl[0-9]+_uxDistanceAndHeading\" title=\"[^\"]*\" src=\"[^\"]*/seek/CacheDir\\.ashx\\?k=([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE);
final Pattern patternCode = Pattern.compile("\\|[^\\w]*(GC[a-z0-9]+)[^\\|]*\\|", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternId = Pattern.compile("name=\"CID\"[^v]*value=\"([0-9]+)\"", Pattern.CASE_INSENSITIVE);
final Pattern patternFavourite = Pattern.compile("<span id=\"ctl00_ContentBody_dlResults_ctl[0-9]+_uxFavoritesValue\" title=\"[^\"]*\" class=\"favorite-rank\">([0-9]+)</span>", Pattern.CASE_INSENSITIVE);
final Pattern patternTotalCnt = Pattern.compile("<td class=\"PageBuilderWidget\"><span>Total Records[^<]*<b>(\\d+)<\\/b>", Pattern.CASE_INSENSITIVE);
final Pattern patternRecaptcha = Pattern.compile("<script[^>]*src=\"[^\"]*/recaptcha/api/challenge\\?k=([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE);
final Pattern patternRecaptchaChallenge = Pattern.compile("challenge : '([^']+)'", Pattern.CASE_INSENSITIVE);
caches.viewstate = findViewstate(page, 0);
caches.viewstate1 = findViewstate(page, 1);
// recaptcha
if (showCaptcha == true) {
try {
String recaptchaJsParam = null;
final Matcher matcherRecaptcha = patternRecaptcha.matcher(page);
while (matcherRecaptcha.find()) {
if (matcherRecaptcha.groupCount() > 0) {
recaptchaJsParam = matcherRecaptcha.group(1);
}
}
if (recaptchaJsParam != null) {
final String recaptchaJs = request(false, "www.google.com", "/recaptcha/api/challenge", "GET", "k=" + urlencode_rfc3986(recaptchaJsParam.trim()), 0, true).getData();
if (recaptchaJs != null && recaptchaJs.length() > 0) {
final Matcher matcherRecaptchaChallenge = patternRecaptchaChallenge.matcher(recaptchaJs);
while (matcherRecaptchaChallenge.find()) {
if (matcherRecaptchaChallenge.groupCount() > 0) {
recaptchaChallenge = matcherRecaptchaChallenge.group(1).trim();
}
}
}
}
} catch (Exception e) {
// failed to parse recaptcha challenge
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse recaptcha challenge");
}
if (thread != null && recaptchaChallenge != null && recaptchaChallenge.length() > 0) {
thread.setChallenge(recaptchaChallenge);
thread.notifyNeed();
}
}
int startPos = -1;
int endPos = -1;
startPos = page.indexOf("<div id=\"ctl00_ContentBody_ResultsPanel\"");
if (startPos == -1) {
Log.e(Settings.tag, "cgeoBase.parseSearch: ID \"ctl00_ContentBody_dlResults\" not found on page");
return null;
}
page = page.substring(startPos); // cut on <table
startPos = page.indexOf(">");
endPos = page.indexOf("ctl00_ContentBody_UnitTxt");
if (startPos == -1 || endPos == -1) {
Log.e(Settings.tag, "cgeoBase.parseSearch: ID \"ctl00_ContentBody_UnitTxt\" not found on page");
return null;
}
page = page.substring(startPos + 1, endPos - startPos + 1); // cut between <table> and </table>
final String[] rows = page.split("<tr class=");
final int rows_count = rows.length;
for (int z = 1; z < rows_count; z++) {
Cache cache = new Cache();
String row = rows[z];
// check for cache type presence
if (row.indexOf("images/wpttypes") == -1) {
continue;
}
try {
final Matcher matcherGuidAndDisabled = patternGuidAndDisabled.matcher(row);
while (matcherGuidAndDisabled.find()) {
if (matcherGuidAndDisabled.groupCount() > 0) {
guids.add(matcherGuidAndDisabled.group(1));
cache.guid = matcherGuidAndDisabled.group(1);
if (matcherGuidAndDisabled.group(4) != null) {
cache.name = Html.fromHtml(matcherGuidAndDisabled.group(4).trim()).toString();
}
if (matcherGuidAndDisabled.group(6) != null) {
cache.location = Html.fromHtml(matcherGuidAndDisabled.group(6).trim()).toString();
}
final String attr = matcherGuidAndDisabled.group(2);
if (attr != null) {
if (attr.contains("Strike") == true) {
cache.disabled = true;
} else {
cache.disabled = false;
}
if (attr.contains("OldWarning") == true) {
cache.archived = true;
} else {
cache.archived = false;
}
}
}
}
} catch (Exception e) {
// failed to parse GUID and/or Disabled
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse GUID and/or Disabled data");
}
if (settings.excludeDisabled == 1 && (cache.disabled == true || cache.archived == true)) {
// skip disabled and archived caches
cache = null;
continue;
}
String inventoryPre = null;
// GC* code
try {
final Matcher matcherCode = patternCode.matcher(row);
while (matcherCode.find()) {
if (matcherCode.groupCount() > 0) {
cache.geocode = matcherCode.group(1).toUpperCase();
}
}
} catch (Exception e) {
// failed to parse code
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache code");
}
// cache type
try {
final Matcher matcherCacheType = patternCacheType.matcher(row);
while (matcherCacheType.find()) {
if (matcherCacheType.groupCount() > 0) {
cache.type = cacheTypes.get(matcherCacheType.group(1).toLowerCase());
}
}
} catch (Exception e) {
// failed to parse type
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache type");
}
// cache direction - image
try {
final Matcher matcherDirection = patternDirection.matcher(row);
while (matcherDirection.find()) {
if (matcherDirection.groupCount() > 0) {
cache.directionImg = matcherDirection.group(1);
}
}
} catch (Exception e) {
// failed to parse direction image
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache direction image");
}
// cache inventory
try {
final Matcher matcherTbs = patternTbs.matcher(row);
while (matcherTbs.find()) {
if (matcherTbs.groupCount() > 0) {
cache.inventoryItems = Integer.parseInt(matcherTbs.group(1));
inventoryPre = matcherTbs.group(2);
}
}
} catch (Exception e) {
// failed to parse inventory
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache inventory (1)");
}
if (inventoryPre != null && inventoryPre.trim().length() > 0) {
try {
final Matcher matcherTbsInside = patternTbsInside.matcher(inventoryPre);
while (matcherTbsInside.find()) {
if (matcherTbsInside.groupCount() == 2 && matcherTbsInside.group(2) != null) {
final String inventoryItem = matcherTbsInside.group(2).toLowerCase();
if (inventoryItem.equals("premium member only cache")) {
continue;
} else {
if (cache.inventoryItems <= 0) {
cache.inventoryItems = 1;
}
}
}
}
} catch (Exception e) {
// failed to parse cache inventory info
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache inventory info");
}
}
// premium cache
if (row.indexOf("/images/small_profile.gif") != -1) {
cache.members = true;
} else {
cache.members = false;
}
// found it
if (row.indexOf("/images/icons/icon_smile.png") != -1) {
cache.found = true;
} else {
cache.found = false;
}
// own it
if (row.indexOf("/images/silk/star.png") != -1) {
cache.own = true;
} else {
cache.own = false;
}
// id
try {
final Matcher matcherId = patternId.matcher(row);
while (matcherId.find()) {
if (matcherId.groupCount() > 0) {
cache.cacheid = matcherId.group(1);
cids.add(cache.cacheid);
}
}
} catch (Exception e) {
// failed to parse cache id
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache id");
}
// favourite count
try {
final Matcher matcherFavourite = patternFavourite.matcher(row);
while (matcherFavourite.find()) {
if (matcherFavourite.groupCount() > 0) {
cache.favouriteCnt = Integer.parseInt(matcherFavourite.group(1));
}
}
} catch (Exception e) {
// failed to parse favourite count
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse favourite count");
}
if (cache.nameSp == null) {
cache.nameSp = (new Spannable.Factory()).newSpannable(cache.name);
if (cache.disabled == true || cache.archived == true) { // strike
cache.nameSp.setSpan(new StrikethroughSpan(), 0, cache.nameSp.toString().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
caches.cacheList.add(cache);
}
// total caches found
try {
final Matcher matcherTotalCnt = patternTotalCnt.matcher(page);
while (matcherTotalCnt.find()) {
if (matcherTotalCnt.groupCount() > 0) {
if (matcherTotalCnt.group(1) != null) {
caches.totalCnt = new Integer(matcherTotalCnt.group(1));
}
}
}
} catch (Exception e) {
// failed to parse cache count
Log.w(Settings.tag, "cgeoBase.parseSearch: Failed to parse cache count");
}
if (thread != null && recaptchaChallenge != null) {
if (thread.getText() == null) {
thread.waitForUser();
}
recaptchaText = thread.getText();
}
if (cids.size() > 0 && (recaptchaChallenge == null || (recaptchaChallenge != null && recaptchaText != null && recaptchaText.length() > 0))) {
Log.i(Settings.tag, "Trying to get .loc for " + cids.size() + " caches");
try {
// get coordinates for parsed caches
final String host = "www.geocaching.com";
final String path = "/seek/nearest.aspx";
final StringBuilder params = new StringBuilder();
params.append("__EVENTTARGET=");
params.append("&");
params.append("__EVENTARGUMENT=");
params.append("&");
params.append("__VIEWSTATE=");
params.append(urlencode_rfc3986(caches.viewstate));
if (caches.viewstate1 != null) {
params.append("&");
params.append("__VIEWSTATE1=");
params.append(urlencode_rfc3986(caches.viewstate1));
params.append("&");
params.append("__VIEWSTATEFIELDCOUNT=2");
}
for (String cid : cids) {
params.append("&");
params.append("CID=");
params.append(urlencode_rfc3986(cid));
}
if (recaptchaChallenge != null && recaptchaText != null && recaptchaText.length() > 0) {
params.append("&");
params.append("recaptcha_challenge_field=");
params.append(urlencode_rfc3986(recaptchaChallenge));
params.append("&");
params.append("recaptcha_response_field=");
params.append(urlencode_rfc3986(recaptchaText));
}
params.append("&");
params.append("ctl00%24ContentBody%24uxDownloadLoc=Download+Waypoints");
final String coordinates = request(false, host, path, "POST", params.toString(), 0, true).getData();
if (coordinates != null && coordinates.length() > 0) {
if (coordinates.indexOf("You have not agreed to the license agreement. The license agreement is required before you can start downloading GPX or LOC files from Geocaching.com") > -1) {
Log.i(Settings.tag, "User has not agreed to the license agreement. Can\'t download .loc file.");
caches.error = errorRetrieve.get(-7);
return caches;
}
}
if (coordinates != null && coordinates.length() > 0) {
final HashMap<String, Coord> cidCoords = new HashMap<String, Coord>();
final Pattern patternCidCode = Pattern.compile("name id=\"([^\"]+)\"");
final Pattern patternCidLat = Pattern.compile("lat=\"([^\"]+)\"");
final Pattern patternCidLon = Pattern.compile("lon=\"([^\"]+)\"");
// premium only >>
final Pattern patternCidDif = Pattern.compile("<difficulty>([^<]+)</difficulty>");
final Pattern patternCidTer = Pattern.compile("<terrain>([^<]+)</terrain>");
final Pattern patternCidCon = Pattern.compile("<container>([^<]+)</container>");
// >> premium only
final String[] points = coordinates.split("<waypoint>");
// parse coordinates
for (String point : points) {
final Coord pointCoord = new Coord();
final Matcher matcherCidCode = patternCidCode.matcher(point);
final Matcher matcherLatCode = patternCidLat.matcher(point);
final Matcher matcherLonCode = patternCidLon.matcher(point);
final Matcher matcherDifCode = patternCidDif.matcher(point);
final Matcher matcherTerCode = patternCidTer.matcher(point);
final Matcher matcherConCode = patternCidCon.matcher(point);
HashMap<String, Object> tmp = null;
if (matcherCidCode.find() == true) {
pointCoord.name = matcherCidCode.group(1).trim().toUpperCase();
}
if (matcherLatCode.find() == true) {
tmp = parseCoordinate(matcherLatCode.group(1), "lat");
pointCoord.latitude = (Double) tmp.get("coordinate");
}
if (matcherLonCode.find() == true) {
tmp = parseCoordinate(matcherLonCode.group(1), "lon");
pointCoord.longitude = (Double) tmp.get("coordinate");
}
if (matcherDifCode.find() == true) {
pointCoord.difficulty = new Float(matcherDifCode.group(1));
}
if (matcherTerCode.find() == true) {
pointCoord.terrain = new Float(matcherTerCode.group(1));
}
if (matcherConCode.find() == true) {
final int size = Integer.parseInt(matcherConCode.group(1));
if (size == 1) {
pointCoord.size = "not chosen";
} else if (size == 2) {
pointCoord.size = "micro";
} else if (size == 3) {
pointCoord.size = "regular";
} else if (size == 4) {
pointCoord.size = "large";
} else if (size == 5) {
pointCoord.size = "virtual";
} else if (size == 6) {
pointCoord.size = "other";
} else if (size == 8) {
pointCoord.size = "small";
} else {
pointCoord.size = "unknown";
}
}
cidCoords.put(pointCoord.name, pointCoord);
}
Log.i(Settings.tag, "Coordinates found in .loc file: " + cidCoords.size());
// save found cache coordinates
for (Cache oneCache : caches.cacheList) {
if (cidCoords.containsKey(oneCache.geocode) == true) {
Coord thisCoords = cidCoords.get(oneCache.geocode);
oneCache.latitude = thisCoords.latitude;
oneCache.longitude = thisCoords.longitude;
oneCache.difficulty = thisCoords.difficulty;
oneCache.terrain = thisCoords.terrain;
oneCache.size = thisCoords.size;
}
}
}
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.parseSearch.CIDs: " + e.toString());
}
}
// get direction images
DirectionImg dirImgDownloader = new DirectionImg(settings);
for (Cache oneCache : caches.cacheList) {
if (oneCache.latitude == null && oneCache.longitude == null && oneCache.direction == null && oneCache.directionImg != null) {
dirImgDownloader.getDrawable(oneCache.geocode, oneCache.directionImg);
}
}
dirImgDownloader = null;
return caches;
}
public CacheWrap parseMapJSON(String url, String data) {
if (data == null || data.length() == 0) {
Log.e(Settings.tag, "cgeoBase.parseMapJSON: No page given");
return null;
}
final CacheWrap caches = new CacheWrap();
caches.url = url;
try {
final JSONObject yoDawg = new JSONObject(data);
final String json = yoDawg.getString("d");
if (json == null || json.length() == 0) {
Log.e(Settings.tag, "cgeoBase.parseMapJSON: No JSON inside JSON");
return null;
}
final JSONObject dataJSON = new JSONObject(json);
final JSONObject extra = dataJSON.getJSONObject("cs");
if (extra != null && extra.length() > 0) {
int count = extra.getInt("count");
if (count > 0 && extra.has("cc")) {
final JSONArray cachesData = extra.getJSONArray("cc");
if (cachesData != null && cachesData.length() > 0) {
JSONObject oneCache = null;
for (int i = 0; i < count; i++) {
oneCache = cachesData.getJSONObject(i);
if (oneCache == null) {
break;
}
final Cache cacheToAdd = new Cache();
cacheToAdd.reliableLatLon = false;
cacheToAdd.geocode = oneCache.getString("gc");
cacheToAdd.latitude = oneCache.getDouble("lat");
cacheToAdd.longitude = oneCache.getDouble("lon");
cacheToAdd.name = oneCache.getString("nn");
cacheToAdd.found = oneCache.getBoolean("f");
cacheToAdd.own = oneCache.getBoolean("o");
cacheToAdd.disabled = !oneCache.getBoolean("ia");
int ctid = oneCache.getInt("ctid");
if (ctid == 2) {
cacheToAdd.type = "traditional";
} else if (ctid == 3) {
cacheToAdd.type = "multi";
} else if (ctid == 4) {
cacheToAdd.type = "virtual";
} else if (ctid == 5) {
cacheToAdd.type = "letterbox";
} else if (ctid == 6) {
cacheToAdd.type = "event";
} else if (ctid == 8) {
cacheToAdd.type = "mystery";
} else if (ctid == 11) {
cacheToAdd.type = "webcam";
} else if (ctid == 13) {
cacheToAdd.type = "cito";
} else if (ctid == 137) {
cacheToAdd.type = "earth";
} else if (ctid == 453) {
cacheToAdd.type = "mega";
} else if (ctid == 1858) {
cacheToAdd.type = "wherigo";
} else if (ctid == 3653) {
cacheToAdd.type = "lost";
}
caches.cacheList.add(cacheToAdd);
}
}
} else {
Log.w(Settings.tag, "There are no caches in viewport");
}
caches.totalCnt = caches.cacheList.size();
}
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.parseMapJSON: " + e.toString());
}
return caches;
}
public CacheWrap parseCache(String page, int reason) {
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.parseCache: No page given");
return null;
}
final Pattern patternGeocode = Pattern.compile("<meta name=\"og:url\" content=\"[^\"]+/(GC[0-9A-Z]+)\"[^>]*>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternCacheId = Pattern.compile("/seek/log\\.aspx\\?ID=(\\d+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternCacheGuid = Pattern.compile("<link rel=\"alternate\" href=\"[^\"]*/datastore/rss_galleryimages\\.ashx\\?guid=([0-9a-z\\-]+)\"[^>]*>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternType = Pattern.compile("<img src=\"[^\"]*/WptTypes/\\d+\\.gif\" alt=\"([^\"]+)\" (title=\"[^\"]*\" )?width=\"32\" height=\"32\"[^>]*>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternName = Pattern.compile("<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_CacheName\">([^<]+)<\\/span>[^<]*<\\/h2>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternSize = Pattern.compile("<div class=\"CacheSize[^\"]*\">[^<]*<p[^>]*>[^S]*Size[^:]*:[^<]*<span[^>]*>[^<]*<img src=\"[^\"]*/icons/container/[a-z_]+\\.gif\" alt=\"Size: ([^\"]+)\"[^>]*>[^<]*<small>[^<]*</small>[^<]*</span>[^<]*</p>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternDifficulty = Pattern.compile("<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\" alt=\"[^\"]+\"[^>]*>[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternTerrain = Pattern.compile("<span id=\"ctl00_ContentBody_Localize6\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\" alt=\"[^\"]+\"[^>]*>[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternOwner = Pattern.compile("<span class=\"minorCacheDetails\">[^\\w]*An?([^\\w]*Event)?[^\\w]*cache[^\\w]*by[^<]*<a href=\"[^\"]+\">([^<]+)</a>[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternOwnerReal = Pattern.compile("<a id=\"ctl00_ContentBody_uxFindLinksHiddenByThisUser\" href=\"[^\"]*/seek/nearest\\.aspx\\?u=*([^\"]+)\">[^<]+</a>", Pattern.CASE_INSENSITIVE);
final Pattern patternHidden = Pattern.compile("<span[^>]*>[^\\w]*Hidden[^:]*:[^\\d]*((\\d+)\\/(\\d+)\\/(\\d+))[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternHiddenEvent = Pattern.compile("<span[^>]*>[^\\w]*Event[^\\w]*Date[^:]*:[^\\w]*[a-zA-Z]+,[^\\d]*((\\d+)[^\\w]*(\\w+)[^\\d]*(\\d+))[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternFavourite = Pattern.compile("<a id=\"uxFavContainerLink\"[^>]*>[^<]*<div[^<]*<span class=\"favorite-value\">[^\\d]*([0-9]+)[^\\d^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternFound = Pattern.compile("<p>[^<]*<a id=\"ctl00_ContentBody_hlFoundItLog\"[^<]*<img src=\".*/images/stockholm/16x16/check\\.gif\"[^>]*>[^<]*</a>[^<]*</p>", Pattern.CASE_INSENSITIVE);
final Pattern patternLatLon = Pattern.compile("<span id=\"uxLatLon\"[^>]*>([^<]*)<\\/span>", Pattern.CASE_INSENSITIVE);
final Pattern patternLocation = Pattern.compile("<span id=\"ctl00_ContentBody_Location\"[^>]*>In ([^<]*)", Pattern.CASE_INSENSITIVE);
final Pattern patternHint = Pattern.compile("<p>([^<]*<strong>)?[^\\w]*Additional Hints([^<]*<\\/strong>)?[^\\(]*\\(<a[^>]+>Encrypt</a>\\)[^<]*<\\/p>[^<]*<div id=\"div_hint\"[^>]*>(.*)</div>[^<]*<div id=[\\'|\"]dk[\\'|\"]", Pattern.CASE_INSENSITIVE);
final Pattern patternDescShort = Pattern.compile("<div class=\"UserSuppliedContent\">[^<]*<span id=\"ctl00_ContentBody_ShortDescription\"[^>]*>((?:(?!</span>[^\\w^<]*</div>).)*)</span>[^\\w^<]*</div>", Pattern.CASE_INSENSITIVE);
final Pattern patternDesc = Pattern.compile("<div class=\"UserSuppliedContent\">[^<]*<span id=\"ctl00_ContentBody_LongDescription\"[^>]*>((?:(?!</span>[^\\w^<]*</div>).)*)</span>[^<]*</div>[^<]*<p>[^<]*</p>[^<]*<p>[^<]*<strong>[^\\w]*Additional Hints</strong>", Pattern.CASE_INSENSITIVE);
final Pattern patternCountLogs = Pattern.compile("<span id=\"ctl00_ContentBody_lblFindCounts\"><p>(.*)<\\/p><\\/span>", Pattern.CASE_INSENSITIVE);
final Pattern patternCountLog = Pattern.compile(" src=\"\\/images\\/icons\\/([^\\.]*).gif\" alt=\"[^\"]*\" title=\"[^\"]*\" />([0-9]*)[^0-9]+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// final Pattern patternLogs = Pattern.compile("<table class=\"LogsTable[^\"]*\"[^>]*>((?:(?!</table>).)*)</table>[^<]*<p", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternLogs = Pattern.compile("<table class=\"LogsTable[^\"]*\"[^>]*>(.*)</table>[^<]*<p", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
/*
* <tr>
* <td class="Nothing">
* <div class="FloatLeft LogDisplayLeft">
* <p class="logOwnerProfileName">
* <strong><a href="/profile/?guid=96c94662-f2c9-450a-99ef-4c034dcde72b" id="184034162">CERV.cz</a></strong>
* </p>
* <p class="logOwnerBadge"><img src='/images/icons/prem_user.gif' title='Premium Member' /> Premium Member</p>
* <p class="logOwnerAvatar"><a href="/profile/?guid=96c94662-f2c9-450a-99ef-4c034dcde72b"><img src="/images/default_avatar.jpg" height='48' width='48' /></a></p>
* <p class="logOwnerStats">
* <img src="/images/icons/icon_smile.png" title="Caches Found" /> 567</div>
* <div class="FloatLeft LogDisplayRight">
* <div class="HalfLeft LogType">
* <strong><img src="http://www.geocaching.com/images/icons/icon_smile.gif" alt="Found it" title="Found it" /> Found it</strong>
* </div>
* <div class="HalfRight AlignRight">
* <span class="minorDetails LogDate">09/03/2011</span>
* </div>
* <div class="Clear LogContent">
* <p class="LogText">13:29 diky za kes!</p>
* <div class="AlignRight">
* <small><a href="log.aspx?LUID=8da01276-7881-4ec9-8d23-8938d7f2984e" title="View Log">View Log</a></small>
* </div></div></div>
* </td>
* </tr>
*/
final Pattern patternLogUser = Pattern.compile("<p class=\"logOwnerProfileName\">[^<]*<strong>[^<]*<a[^>]*>([^<]+)</a>[^<]*</strong>[^<]*</p>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternLogFounds = Pattern.compile("<p class=\"logOwnerStats\"><img[^>]*>[^\\d]*(\\d+)[^<]*</div>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternLogIcon = Pattern.compile("<strong>[^<]*<img src=\"[^\"]*/images/icons/([^\"]+)\\.gif\"[^>]*>[^<]+</strong>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternLogDate = Pattern.compile("<span class=\"minorDetails LogDate\">([0-9]+/[0-9]+/[0-9]+)[^<]*</span>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternLogText = Pattern.compile("<p class=\"LogText\">((?:(?!</p>).)*)</p>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Pattern patternAttributes = Pattern.compile("<h3 class=\"WidgetHeader\">[^<]*<img[^>]+>[^\\w]*Attributes[^<]*</h3>[^<]*<div class=\"WidgetBody\">(([^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+)[^<]*<p", Pattern.CASE_INSENSITIVE);
final Pattern patternAttributesInside = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE);
final Pattern patternSpoilers = Pattern.compile("<span id=\"ctl00_ContentBody_Images\">((<a href=\"[^\"]+\"[^>]*>[^<]*<img[^>]+>[^<]*<span>[^>]+</span>[^<]*</a>[^<]*<br[^>]*>([^<]*(<br[^>]*>)+)?)+)[^<]*</span>", Pattern.CASE_INSENSITIVE);
final Pattern patternSpoilersInside = Pattern.compile("[^<]*<a href=\"([^\"]+)\"[^>]*>[^<]*<img[^>]+>[^<]*<span>([^>]+)</span>[^<]*</a>[^<]*<br[^>]*>(([^<]*)(<br[^<]*>)+)?", Pattern.CASE_INSENSITIVE);
final Pattern patternInventory = Pattern.compile("<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">[^\\w]*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?", Pattern.CASE_INSENSITIVE);
final Pattern patternInventoryInside = Pattern.compile("[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>", Pattern.CASE_INSENSITIVE);
final CacheWrap caches = new CacheWrap();
final Cache cache = new Cache();
if (page.indexOf("Cache is Unpublished") > -1) {
caches.error = "cache was unpublished";
return caches;
}
if (page.indexOf("Sorry, the owner of this listing has made it viewable to Premium Members only.") != -1) {
caches.error = "requested cache is for premium members only";
return caches;
}
if (page.indexOf("has chosen to make this cache listing visible to Premium Members only.") != -1) {
caches.error = "requested cache is for premium members only";
return caches;
}
if (page.indexOf("<li>This cache is temporarily unavailable.") != -1) {
cache.disabled = true;
} else {
cache.disabled = false;
}
if (page.indexOf("<li>This cache has been archived,") != -1) {
cache.archived = true;
} else {
cache.archived = false;
}
if (page.indexOf("<p class=\"Warning\">This is a Premium Member Only cache.</p>") != -1) {
cache.members = true;
} else {
cache.members = false;
}
cache.reason = reason;
// cache geocode
try {
final Matcher matcherGeocode = patternGeocode.matcher(page);
while (matcherGeocode.find()) {
if (matcherGeocode.groupCount() > 0) {
cache.geocode = (String) matcherGeocode.group(1);
}
}
} catch (Exception e) {
// failed to parse cache geocode
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache geocode");
}
// cache id
try {
final Matcher matcherCacheId = patternCacheId.matcher(page);
while (matcherCacheId.find()) {
if (matcherCacheId.groupCount() > 0) {
cache.cacheid = (String) matcherCacheId.group(1);
}
}
} catch (Exception e) {
// failed to parse cache id
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache id");
}
// cache guid
try {
final Matcher matcherCacheGuid = patternCacheGuid.matcher(page);
while (matcherCacheGuid.find()) {
if (matcherCacheGuid.groupCount() > 0) {
cache.guid = (String) matcherCacheGuid.group(1);
}
}
} catch (Exception e) {
// failed to parse cache guid
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache guid");
}
// name
try {
final Matcher matcherName = patternName.matcher(page);
while (matcherName.find()) {
if (matcherName.groupCount() > 0) {
cache.name = Html.fromHtml(matcherName.group(1)).toString();
}
}
} catch (Exception e) {
// failed to parse cache name
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache name");
}
// owner real name
try {
final Matcher matcherOwnerReal = patternOwnerReal.matcher(page);
while (matcherOwnerReal.find()) {
if (matcherOwnerReal.groupCount() > 0) {
cache.ownerReal = URLDecoder.decode(matcherOwnerReal.group(1));
}
}
} catch (Exception e) {
// failed to parse owner real name
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache owner real name");
}
final String username = settings.getUsername();
if (cache.ownerReal != null && username != null && cache.ownerReal.equalsIgnoreCase(username)) {
cache.own = true;
}
int pos = -1;
String tableInside = page;
pos = tableInside.indexOf("id=\"cacheDetails\"");
if (pos == -1) {
Log.e(Settings.tag, "cgeoBase.parseCache: ID \"cacheDetails\" not found on page");
return null;
}
tableInside = tableInside.substring(pos);
pos = tableInside.indexOf("<div class=\"CacheInformationTable\"");
if (pos == -1) {
Log.e(Settings.tag, "cgeoBase.parseCache: ID \"CacheInformationTable\" not found on page");
return null;
}
tableInside = tableInside.substring(0, pos);
if (tableInside != null && tableInside.length() > 0) {
// cache terrain
try {
final Matcher matcherTerrain = patternTerrain.matcher(tableInside);
while (matcherTerrain.find()) {
if (matcherTerrain.groupCount() > 0) {
cache.terrain = new Float(Pattern.compile("_").matcher(matcherTerrain.group(1)).replaceAll("."));
}
}
} catch (Exception e) {
// failed to parse terrain
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache terrain");
}
// cache difficulty
try {
final Matcher matcherDifficulty = patternDifficulty.matcher(tableInside);
while (matcherDifficulty.find()) {
if (matcherDifficulty.groupCount() > 0) {
cache.difficulty = new Float(Pattern.compile("_").matcher(matcherDifficulty.group(1)).replaceAll("."));
}
}
} catch (Exception e) {
// failed to parse difficulty
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache difficulty");
}
// owner
try {
final Matcher matcherOwner = patternOwner.matcher(tableInside);
while (matcherOwner.find()) {
if (matcherOwner.groupCount() > 0) {
cache.owner = Html.fromHtml(matcherOwner.group(2)).toString();
}
}
} catch (Exception e) {
// failed to parse owner
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache owner");
}
// hidden
try {
final Matcher matcherHidden = patternHidden.matcher(tableInside);
while (matcherHidden.find()) {
if (matcherHidden.groupCount() > 0) {
cache.hidden = dateIn.parse(matcherHidden.group(1));
}
}
} catch (Exception e) {
// failed to parse cache hidden date
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache hidden date");
}
if (cache.hidden == null) {
// event date
try {
final Matcher matcherHiddenEvent = patternHiddenEvent.matcher(tableInside);
while (matcherHiddenEvent.find()) {
if (matcherHiddenEvent.groupCount() > 0) {
cache.hidden = dateEvIn.parse(matcherHiddenEvent.group(1));
}
}
} catch (Exception e) {
// failed to parse cache event date
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache event date");
}
}
// favourite
try {
final Matcher matcherFavourite = patternFavourite.matcher(tableInside);
while (matcherFavourite.find()) {
if (matcherFavourite.groupCount() > 0) {
cache.favouriteCnt = Integer.parseInt(matcherFavourite.group(1));
}
}
} catch (Exception e) {
// failed to parse favourite count
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse favourite count");
}
// cache size
try {
final Matcher matcherSize = patternSize.matcher(tableInside);
while (matcherSize.find()) {
if (matcherSize.groupCount() > 0) {
cache.size = matcherSize.group(1).toLowerCase();
}
}
} catch (Exception e) {
// failed to parse size
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache size");
}
}
// cache found
try {
final Matcher matcherFound = patternFound.matcher(page);
while (matcherFound.find()) {
if (matcherFound.group() != null && matcherFound.group().length() > 0) {
cache.found = true;
}
}
} catch (Exception e) {
// failed to parse found
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse found");
}
// cache type
try {
final Matcher matcherType = patternType.matcher(page);
while (matcherType.find()) {
if (matcherType.groupCount() > 0) {
cache.type = cacheTypes.get(matcherType.group(1).toLowerCase());
}
}
} catch (Exception e) {
// failed to parse type
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache type");
}
// latitude and logitude
try {
final Matcher matcherLatLon = patternLatLon.matcher(page);
while (matcherLatLon.find()) {
if (matcherLatLon.groupCount() > 0) {
cache.latlon = matcherLatLon.group(1);
HashMap<String, Object> tmp = this.parseLatlon(cache.latlon);
if (tmp.size() > 0) {
cache.latitude = (Double) tmp.get("latitude");
cache.longitude = (Double) tmp.get("longitude");
cache.latitudeString = (String) tmp.get("latitudeString");
cache.longitudeString = (String) tmp.get("longitudeString");
cache.reliableLatLon = true;
}
tmp = null;
}
}
} catch (Exception e) {
// failed to parse latitude and/or longitude
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache coordinates");
}
// cache location
try {
final Matcher matcherLocation = patternLocation.matcher(page);
while (matcherLocation.find()) {
if (matcherLocation.groupCount() > 0) {
cache.location = matcherLocation.group(1);
}
}
} catch (Exception e) {
// failed to parse location
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache location");
}
// cache hint
try {
final Matcher matcherHint = patternHint.matcher(page);
while (matcherHint.find()) {
if (matcherHint.groupCount() > 2 && matcherHint.group(3) != null) {
// replace linebreak and paragraph tags
String hint = Pattern.compile("<(br|p)[^>]*>").matcher(matcherHint.group(3)).replaceAll("\n");
if (hint != null) {
cache.hint = hint.replaceAll(Pattern.quote("</p>"), "").trim();
}
}
}
} catch (Exception e) {
// failed to parse hint
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache hint");
}
// cache short description
try {
final Matcher matcherDescShort = patternDescShort.matcher(page);
while (matcherDescShort.find()) {
if (matcherDescShort.groupCount() > 0) {
cache.shortdesc = matcherDescShort.group(1).trim();
}
}
} catch (Exception e) {
// failed to parse short description
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache short description");
}
// cache description
try {
final Matcher matcherDesc = patternDesc.matcher(page);
while (matcherDesc.find()) {
if (matcherDesc.groupCount() > 0) {
cache.description = matcherDesc.group(1);
}
}
} catch (Exception e) {
// failed to parse short description
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache description");
}
// cache attributes
try {
final Matcher matcherAttributes = patternAttributes.matcher(page);
while (matcherAttributes.find()) {
if (matcherAttributes.groupCount() > 0) {
final String attributesPre = matcherAttributes.group(1);
final Matcher matcherAttributesInside = patternAttributesInside.matcher(attributesPre);
while (matcherAttributesInside.find()) {
if (matcherAttributesInside.groupCount() > 1 && matcherAttributesInside.group(2).equalsIgnoreCase("blank") != true) {
if (cache.attributes == null) {
cache.attributes = new ArrayList<String>();
}
// by default, use the tooltip of the attribute
String attribute = matcherAttributesInside.group(2).toLowerCase();
// if the image name can be recognized, use the image name as attribute
String imageName = matcherAttributesInside.group(1).trim();
if (imageName.length() > 0) {
int start = imageName.lastIndexOf('/');
int end = imageName.lastIndexOf('.');
if (start >= 0 && end>= 0) {
attribute = imageName.substring(start + 1, end).replace('-', '_');
}
}
cache.attributes.add(attribute);
}
}
}
}
} catch (Exception e) {
// failed to parse cache attributes
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache attributes");
}
// cache spoilers
try {
final Matcher matcherSpoilers = patternSpoilers.matcher(page);
while (matcherSpoilers.find()) {
if (matcherSpoilers.groupCount() > 0) {
final String spoilersPre = matcherSpoilers.group(1);
final Matcher matcherSpoilersInside = patternSpoilersInside.matcher(spoilersPre);
while (matcherSpoilersInside.find()) {
if (matcherSpoilersInside.groupCount() > 0) {
final Spoiler spoiler = new Spoiler();
spoiler.url = matcherSpoilersInside.group(1);
if (matcherSpoilersInside.group(2) != null) {
spoiler.title = matcherSpoilersInside.group(2);
}
if (matcherSpoilersInside.group(4) != null) {
spoiler.description = matcherSpoilersInside.group(4);
}
if (cache.spoilers == null) {
cache.spoilers = new ArrayList<Spoiler>();
}
cache.spoilers.add(spoiler);
}
}
}
}
} catch (Exception e) {
// failed to parse cache spoilers
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache spoilers");
}
// cache inventory
try {
cache.inventoryItems = 0;
final Matcher matcherInventory = patternInventory.matcher(page);
while (matcherInventory.find()) {
if (cache.inventory == null) {
cache.inventory = new ArrayList<Trackable>();
}
if (matcherInventory.groupCount() > 1) {
final String inventoryPre = matcherInventory.group(2);
if (inventoryPre != null && inventoryPre.length() > 0) {
final Matcher matcherInventoryInside = patternInventoryInside.matcher(inventoryPre);
while (matcherInventoryInside.find()) {
if (matcherInventoryInside.groupCount() > 0) {
final Trackable inventoryItem = new Trackable();
inventoryItem.guid = matcherInventoryInside.group(1);
inventoryItem.name = matcherInventoryInside.group(2);
cache.inventory.add(inventoryItem);
cache.inventoryItems++;
}
}
}
}
}
} catch (Exception e) {
// failed to parse cache inventory
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache inventory (2)");
}
// cache logs counts
try {
final Matcher matcherLogCounts = patternCountLogs.matcher(page);
while (matcherLogCounts.find()) {
if (matcherLogCounts.groupCount() > 0) {
final String[] logs = matcherLogCounts.group(1).split("<img");
final int logsCnt = logs.length;
for (int k = 1; k < logsCnt; k++) {
Integer type = null;
Integer count = null;
final Matcher matcherLog = patternCountLog.matcher(logs[k]);
if (matcherLog.find()) {
String typeStr = matcherLog.group(1);
String countStr = matcherLog.group(2);
if (typeStr != null && typeStr.length() > 0) {
if (logTypes.containsKey(typeStr.toLowerCase()) == true) {
type = logTypes.get(typeStr.toLowerCase());
}
}
if (countStr != null && countStr.length() > 0) {
count = Integer.parseInt(countStr);
}
if (type != null && count != null) {
cache.logCounts.put(type, count);
}
}
}
}
}
} catch (Exception e) {
// failed to parse logs
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache log count");
}
// cache logs
try {
final Matcher matcherLogs = patternLogs.matcher(page);
while (matcherLogs.find()) {
Log.d(">>>>", "cnt: " + matcherLogs.groupCount());
if (matcherLogs.groupCount() > 0) {
final String[] logs = matcherLogs.group(1).split("</tr><tr>");
final int logsCnt = logs.length;
for (int k = 0; k < logsCnt; k++) {
final CacheLog logDone = new CacheLog();
Matcher matcher;
matcher = patternLogUser.matcher(logs[k]);
if (matcher.find() && matcher.groupCount() > 0) {
logDone.author = matcher.group(1).trim();
logDone.author = Html.fromHtml(logDone.author).toString();
}
matcher = patternLogFounds.matcher(logs[k]);
if (matcher.find() && matcher.groupCount() > 0) {
try {
logDone.found = Integer.parseInt(matcher.group(1).trim());
} catch (Exception e) {
// NaN
}
}
matcher = patternLogIcon.matcher(logs[k]);
if (matcher.find() && matcher.groupCount() > 0) {
if (logTypes.containsKey(matcher.group(1).toLowerCase()) == true) {
logDone.type = logTypes.get(matcher.group(1).toLowerCase());
} else {
logDone.type = logTypes.get("icon_note");
}
}
matcher = patternLogDate.matcher(logs[k]);
if (matcher.find() && matcher.groupCount() > 0) {
Date logDate = dateLogIn.parse(matcher.group(1));
if (logDate != null) {
logDone.date = logDate.getTime();
}
}
matcher = patternLogText.matcher(logs[k]);
if (matcher.find() && matcher.groupCount() > 0) {
logDone.log = matcher.group(1).trim();
}
if (cache.logs == null) {
cache.logs = new ArrayList<CacheLog>();
}
cache.logs.add(logDone);
}
}
}
} catch (Exception e) {
// failed to parse logs
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache logs");
}
int wpBegin = 0;
int wpEnd = 0;
wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
if (wpBegin != -1) { // parse waypoints
final Pattern patternWpType = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg", Pattern.CASE_INSENSITIVE);
final Pattern patternWpPrefixOrLookupOrLatlon = Pattern.compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>", Pattern.CASE_INSENSITIVE);
final Pattern patternWpName = Pattern.compile(">[^<]*<a[^>]+>([^<]*)<\\/a>", Pattern.CASE_INSENSITIVE);
final Pattern patternWpNote = Pattern.compile("colspan=\"6\">(.*)<\\/td>", Pattern.CASE_INSENSITIVE);
String wpList = page.substring(wpBegin);
wpEnd = wpList.indexOf("</p>");
if (wpEnd > -1 && wpEnd <= wpList.length()) {
wpList = wpList.substring(0, wpEnd);
}
if (wpList.indexOf("No additional waypoints to display.") == -1) {
wpEnd = wpList.indexOf("</table>");
wpList = wpList.substring(0, wpEnd);
wpBegin = wpList.indexOf("<tbody>");
wpEnd = wpList.indexOf("</tbody>");
if (wpBegin >= 0 && wpEnd >= 0 && wpEnd <= wpList.length()) {
wpList = wpList.substring(wpBegin + 7, wpEnd);
}
final String[] wpItems = wpList.split("<tr");
String[] wp;
for (int j = 1; j < wpItems.length; j++) {
final Waypoint waypoint = new Waypoint();
wp = wpItems[j].split("<td");
// waypoint type
try {
final Matcher matcherWpType = patternWpType.matcher(wp[3]);
while (matcherWpType.find()) {
if (matcherWpType.groupCount() > 0) {
waypoint.type = matcherWpType.group(1);
if (waypoint.type != null) {
waypoint.type = waypoint.type.trim();
}
}
}
} catch (Exception e) {
// failed to parse type
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint type");
}
// waypoint prefix
try {
final Matcher matcherWpPrefix = patternWpPrefixOrLookupOrLatlon.matcher(wp[4]);
while (matcherWpPrefix.find()) {
if (matcherWpPrefix.groupCount() > 1) {
waypoint.prefix = matcherWpPrefix.group(2);
if (waypoint.prefix != null) {
waypoint.prefix = waypoint.prefix.trim();
}
}
}
} catch (Exception e) {
// failed to parse prefix
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint prefix");
}
// waypoint lookup
try {
final Matcher matcherWpLookup = patternWpPrefixOrLookupOrLatlon.matcher(wp[5]);
while (matcherWpLookup.find()) {
if (matcherWpLookup.groupCount() > 1) {
waypoint.lookup = matcherWpLookup.group(2);
if (waypoint.lookup != null) {
waypoint.lookup = waypoint.lookup.trim();
}
}
}
} catch (Exception e) {
// failed to parse lookup
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint lookup");
}
// waypoint name
try {
final Matcher matcherWpName = patternWpName.matcher(wp[6]);
while (matcherWpName.find()) {
if (matcherWpName.groupCount() > 0) {
waypoint.name = matcherWpName.group(1);
if (waypoint.name != null) {
waypoint.name = waypoint.name.trim();
}
}
}
} catch (Exception e) {
// failed to parse name
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint name");
}
// waypoint latitude and logitude
try {
final Matcher matcherWpLatLon = patternWpPrefixOrLookupOrLatlon.matcher(wp[7]);
while (matcherWpLatLon.find()) {
if (matcherWpLatLon.groupCount() > 1) {
waypoint.latlon = Html.fromHtml(matcherWpLatLon.group(2)).toString();
final HashMap<String, Object> tmp = this.parseLatlon(waypoint.latlon);
if (tmp.size() > 0) {
waypoint.latitude = (Double) tmp.get("latitude");
waypoint.longitude = (Double) tmp.get("longitude");
waypoint.latitudeString = (String) tmp.get("latitudeString");
waypoint.longitudeString = (String) tmp.get("longitudeString");
}
}
}
} catch (Exception e) {
// failed to parse latitude and/or longitude
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint coordinates");
}
j++;
if (wpItems.length > j) {
wp = wpItems[j].split("<td");
}
// waypoint note
try {
final Matcher matcherWpNote = patternWpNote.matcher(wp[3]);
while (matcherWpNote.find()) {
if (matcherWpNote.groupCount() > 0) {
waypoint.note = matcherWpNote.group(1);
if (waypoint.note != null) {
waypoint.note = waypoint.note.trim();
}
}
}
} catch (Exception e) {
// failed to parse note
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse waypoint note");
}
if (cache.waypoints == null)
cache.waypoints = new ArrayList<Waypoint>();
cache.waypoints.add(waypoint);
}
}
}
if (cache.latitude != null && cache.longitude != null) {
cache.elevation = getElevation(cache.latitude, cache.longitude);
}
cache.updated = System.currentTimeMillis();
cache.detailedUpdate = System.currentTimeMillis();
cache.detailed = true;
caches.cacheList.add(cache);
return caches;
}
public Long parseGPX(App app, File file, int listId, Handler handler) {
Search search = new Search();
long searchId = 0l;
try {
GPXParser GPXparser = new GPXParser(app, this, listId, search);
searchId = GPXparser.parse(file, 10, handler);
if (searchId == 0l) {
searchId = GPXparser.parse(file, 11, handler);
}
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.parseGPX: " + e.toString());
}
Log.i(Settings.tag, "Caches found in .gpx file: " + app.getCount(searchId));
return search.getCurrentId();
}
public Trackable parseTrackable(String page) {
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.parseTrackable: No page given");
return null;
}
final Pattern patternTrackableId = Pattern.compile("<a id=\"ctl00_ContentBody_LogLink\" title=\"[^\"]*\" href=\".*log\\.aspx\\?wid=([a-z0-9\\-]+)\"[^>]*>[^<]*</a>", Pattern.CASE_INSENSITIVE);
final Pattern patternGeocode = Pattern.compile("<span id=\"ctl00_ContentBody_BugDetails_BugTBNum\" String=\"[^\"]*\">Use[^<]*<strong>(TB[0-9a-z]+)[^<]*</strong> to reference this item.[^<]*</span>", Pattern.CASE_INSENSITIVE);
final Pattern patternName = Pattern.compile("<h2>([^<]*<img[^>]*>)?[^<]*<span id=\"ctl00_ContentBody_lbHeading\">([^<]+)</span>[^<]*</h2>", Pattern.CASE_INSENSITIVE);
final Pattern patternOwner = Pattern.compile("<dt>[^\\w]*Owner:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugOwner\" title=\"[^\"]*\" href=\"[^\"]*/profile/\\?guid=([a-z0-9\\-]+)\">([^<]+)<\\/a>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternReleased = Pattern.compile("<dt>[^\\w]*Released:[^<]*</dt>[^<]*<dd>[^<]*<span id=\"ctl00_ContentBody_BugDetails_BugReleaseDate\">([^<]+)<\\/span>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternOrigin = Pattern.compile("<dt>[^\\w]*Origin:[^<]*</dt>[^<]*<dd>[^<]*<span id=\"ctl00_ContentBody_BugDetails_BugOrigin\">([^<]+)<\\/span>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternSpottedCache = Pattern.compile("<dt>[^\\w]*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\" title=\"[^\"]*\" href=\"[^\"]*/seek/cache_details.aspx\\?guid=([a-z0-9\\-]+)\">In ([^<]+)</a>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternSpottedUser = Pattern.compile("<dt>[^\\w]*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\" href=\"[^\"]*/profile/\\?guid=([a-z0-9\\-]+)\">In the hands of ([^<]+).</a>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternSpottedUnknown = Pattern.compile("<dt>[^\\w]*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\">Unknown Location[^<]*</a>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternSpottedOwner = Pattern.compile("<dt>[^\\w]*Recently Spotted:[^<]*</dt>[^<]*<dd>[^<]*<a id=\"ctl00_ContentBody_BugDetails_BugLocation\">In the hands of the owner[^<]*</a>[^<]*</dd>", Pattern.CASE_INSENSITIVE);
final Pattern patternGoal = Pattern.compile("<h3>[^\\w]*Current GOAL[^<]*</h3>[^<]*<p[^>]*>(.*)</p>[^<]*<h3>[^\\w]*About This Item[^<]*</h3>", Pattern.CASE_INSENSITIVE);
final Pattern patternDetailsImage = Pattern.compile("<h3>[^\\w]*About This Item[^<]*</h3>([^<]*<p>([^<]*<img id=\"ctl00_ContentBody_BugDetails_BugImage\" class=\"[^\"]+\" src=\"([^\"]+)\"[^>]*>)?[^<]*</p>)?[^<]*<p[^>]*>(.*)</p>[^<]*<div id=\"ctl00_ContentBody_BugDetails_uxAbuseReport\">", Pattern.CASE_INSENSITIVE);
final Pattern patternLogs = Pattern.compile("<table class=\"TrackableItemLogTable Table\">(.*)<\\/table>[^<]*<ul", Pattern.CASE_INSENSITIVE);
final Pattern patternIcon = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE);
final Pattern patternType = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"[^\"]+\" alt=\"([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE);
final Pattern patternDistance = Pattern.compile("<h4[^>]*[^\\w]*Tracking History \\(([0-9\\.,]+(km|mi))[^\\)]*\\)", Pattern.CASE_INSENSITIVE);
final Trackable trackable = new Trackable();
// trackable geocode
try {
final Matcher matcherGeocode = patternGeocode.matcher(page);
while (matcherGeocode.find()) {
if (matcherGeocode.groupCount() > 0) {
trackable.geocode = matcherGeocode.group(1).toUpperCase();
}
}
} catch (Exception e) {
// failed to parse trackable geocode
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable geocode");
}
// trackable id
try {
final Matcher matcherTrackableId = patternTrackableId.matcher(page);
while (matcherTrackableId.find()) {
if (matcherTrackableId.groupCount() > 0) {
trackable.guid = matcherTrackableId.group(1);
}
}
} catch (Exception e) {
// failed to parse trackable id
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable id");
}
// trackable icon
try {
final Matcher matcherTrackableIcon = patternIcon.matcher(page);
while (matcherTrackableIcon.find()) {
if (matcherTrackableIcon.groupCount() > 0) {
trackable.iconUrl = matcherTrackableIcon.group(1);
}
}
} catch (Exception e) {
// failed to parse trackable icon
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable icon");
}
// trackable name
try {
final Matcher matcherName = patternName.matcher(page);
while (matcherName.find()) {
if (matcherName.groupCount() > 1) {
trackable.name = matcherName.group(2);
}
}
} catch (Exception e) {
// failed to parse trackable name
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable name");
}
// trackable type
if (trackable.name != null && trackable.name.length() > 0) {
try {
final Matcher matcherType = patternType.matcher(page);
while (matcherType.find()) {
if (matcherType.groupCount() > 0) {
trackable.type = matcherType.group(1);
}
}
} catch (Exception e) {
// failed to parse trackable type
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable type");
}
}
// trackable owner name
try {
final Matcher matcherOwner = patternOwner.matcher(page);
while (matcherOwner.find()) {
if (matcherOwner.groupCount() > 0) {
trackable.ownerGuid = matcherOwner.group(1);
trackable.owner = matcherOwner.group(2);
}
}
} catch (Exception e) {
// failed to parse trackable owner name
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable owner name");
}
// trackable origin
try {
final Matcher matcherOrigin = patternOrigin.matcher(page);
while (matcherOrigin.find()) {
if (matcherOrigin.groupCount() > 0) {
trackable.origin = matcherOrigin.group(1);
}
}
} catch (Exception e) {
// failed to parse trackable origin
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable origin");
}
// trackable spotted
try {
final Matcher matcherSpottedCache = patternSpottedCache.matcher(page);
while (matcherSpottedCache.find()) {
if (matcherSpottedCache.groupCount() > 0) {
trackable.spottedGuid = matcherSpottedCache.group(1);
trackable.spottedName = matcherSpottedCache.group(2);
trackable.spottedType = Trackable.SPOTTED_CACHE;
}
}
final Matcher matcherSpottedUser = patternSpottedUser.matcher(page);
while (matcherSpottedUser.find()) {
if (matcherSpottedUser.groupCount() > 0) {
trackable.spottedGuid = matcherSpottedUser.group(1);
trackable.spottedName = matcherSpottedUser.group(2);
trackable.spottedType = Trackable.SPOTTED_USER;
}
}
final Matcher matcherSpottedUnknown = patternSpottedUnknown.matcher(page);
if (matcherSpottedUnknown.find()) {
trackable.spottedType = Trackable.SPOTTED_UNKNOWN;
}
final Matcher matcherSpottedOwner = patternSpottedOwner.matcher(page);
if (matcherSpottedOwner.find()) {
trackable.spottedType = Trackable.SPOTTED_OWNER;
}
} catch (Exception e) {
// failed to parse trackable last known place
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable last known place");
}
// released
try {
final Matcher matcherReleased = patternReleased.matcher(page);
while (matcherReleased.find()) {
if (matcherReleased.groupCount() > 0 && matcherReleased.group(1) != null) {
try {
if (trackable.released == null) {
trackable.released = dateTbIn1.parse(matcherReleased.group(1));
}
} catch (Exception e) {
//
}
try {
if (trackable.released == null) {
trackable.released = dateTbIn2.parse(matcherReleased.group(1));
}
} catch (Exception e) {
//
}
}
}
} catch (Exception e) {
// failed to parse trackable released date
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable released date");
}
// trackable distance
try {
final Matcher matcherDistance = patternDistance.matcher(page);
while (matcherDistance.find()) {
if (matcherDistance.groupCount() > 0) {
trackable.distance = parseDistance(matcherDistance.group(1));
}
}
} catch (Exception e) {
// failed to parse trackable distance
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable distance");
}
// trackable goal
try {
final Matcher matcherGoal = patternGoal.matcher(page);
while (matcherGoal.find()) {
if (matcherGoal.groupCount() > 0) {
trackable.goal = matcherGoal.group(1);
}
}
} catch (Exception e) {
// failed to parse trackable goal
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable goal");
}
// trackable details & image
try {
final Matcher matcherDetailsImage = patternDetailsImage.matcher(page);
while (matcherDetailsImage.find()) {
if (matcherDetailsImage.groupCount() > 0) {
final String image = matcherDetailsImage.group(3);
final String details = matcherDetailsImage.group(4);
if (image != null) {
trackable.image = image;
}
if (details != null) {
trackable.details = details;
}
}
}
} catch (Exception e) {
// failed to parse trackable details & image
Log.w(Settings.tag, "cgeoBase.parseTrackable: Failed to parse trackable details & image");
}
// trackable logs
try {
final Matcher matcherLogs = patternLogs.matcher(page);
while (matcherLogs.find()) {
if (matcherLogs.groupCount() > 0) {
final Pattern patternLog = Pattern.compile("[^>]*>" +
"[^<]*<td[^<]*<img src=[\"|'].*\\/icons\\/([^\\.]+)\\.[a-z]{2,5}[\"|'][^>]*> (\\d+).(\\d+).(\\d+)[^<]*</td>" +
"[^<]*<td>[^<]*<a href=[^>]+>([^<]+)<.a>([^<]*|[^<]*<a href=[\"|'].*guid=([^\"]*)\">([^<]*)</a>[^<]*)</td>" +
"[^<]*<td>[^<]*</td>" +
"[^<]*<td[^<]*<a href=[^>]+>[^<]+</a>[^<]*</td>[^<]*</tr>" +
"[^<]*<tr[^>]*>[^<]*<td[^>]*>(.*?)</td>[^<]*</tr>.*" +
"");
// 1 filename == type
// 2 month
// 3 date
// 4 year
// 5 user
// 6 action dependent
// 7 cache guid
// 8 cache name
// 9 text
final String[] logs = matcherLogs.group(1).split("<tr class=\"Data BorderTop");
final int logsCnt = logs.length;
for (int k = 1; k < logsCnt; k++) {
final Matcher matcherLog = patternLog.matcher(logs[k]);
if (matcherLog.find()) {
final CacheLog logDone = new CacheLog();
String logTmp = matcherLog.group(9);
logTmp = Pattern.compile("<p>").matcher(logTmp).replaceAll("\n");
logTmp = Pattern.compile("<br[^>]*>").matcher(logTmp).replaceAll("\n");
logTmp = Pattern.compile("<\\/p>").matcher(logTmp).replaceAll("");
logTmp = Pattern.compile("\r+").matcher(logTmp).replaceAll("\n");
int day = -1;
try {
day = Integer.parseInt(matcherLog.group(3));
} catch (Exception e) {
Log.w(Settings.tag, "Failed to parse logs date (day): " + e.toString());
}
int month = -1;
try {
month = Integer.parseInt(matcherLog.group(2));
month -= 1;
} catch (Exception e) {
Log.w(Settings.tag, "Failed to parse logs date (month): " + e.toString());
}
int year = -1;
try {
year = Integer.parseInt(matcherLog.group(4));
} catch (Exception e) {
Log.w(Settings.tag, "Failed to parse logs date (year): " + e.toString());
}
long logDate;
if (year > 0 && month >= 0 && day > 0) {
Calendar date = Calendar.getInstance();
date.set(year, month, day, 12, 0, 0);
logDate = date.getTimeInMillis();
logDate = (long) (Math.ceil(logDate / 1000)) * 1000;
} else {
logDate = 0;
}
if (logTypes.containsKey(matcherLog.group(1).toLowerCase()) == true) {
logDone.type = logTypes.get(matcherLog.group(1).toLowerCase());
} else {
logDone.type = logTypes.get("icon_note");
}
logDone.author = Html.fromHtml(matcherLog.group(5)).toString();
logDone.date = logDate;
logDone.log = logTmp;
if (matcherLog.group(7) != null && matcherLog.group(8) != null) {
logDone.cacheGuid = matcherLog.group(7);
logDone.cacheName = matcherLog.group(8);
}
trackable.logs.add(logDone);
}
}
}
}
} catch (Exception e) {
// failed to parse logs
Log.w(Settings.tag, "cgeoBase.parseCache: Failed to parse cache logs");
}
app.saveTrackable(trackable);
return trackable;
}
public ArrayList<Integer> parseTypes(String page) {
if (page == null || page.length() == 0) {
return null;
}
final ArrayList<Integer> types = new ArrayList<Integer>();
final Pattern typeBoxPattern = Pattern.compile("<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$ddLogType\" id=\"ctl00_ContentBody_LogBookPanel1_ddLogType\"[^>]*>"
+ "(([^<]*<option[^>]*>[^<]+</option>)+)[^<]*</select>", Pattern.CASE_INSENSITIVE);
final Matcher typeBoxMatcher = typeBoxPattern.matcher(page);
String typesText = null;
if (typeBoxMatcher.find()) {
if (typeBoxMatcher.groupCount() > 0) {
typesText = typeBoxMatcher.group(1);
}
}
if (typesText != null) {
final Pattern typePattern = Pattern.compile("<option( selected=\"selected\")? value=\"(\\d+)\">[^<]+</option>", Pattern.CASE_INSENSITIVE);
final Matcher typeMatcher = typePattern.matcher(typesText);
while (typeMatcher.find()) {
if (typeMatcher.groupCount() > 1) {
final int type = Integer.parseInt(typeMatcher.group(2));
if (type > 0) {
types.add(type);
}
}
}
}
return types;
}
public ArrayList<TrackableLog> parseTrackableLog(String page) {
if (page == null || page.length() == 0) {
return null;
}
final ArrayList<TrackableLog> trackables = new ArrayList<TrackableLog>();
int startPos = -1;
int endPos = -1;
startPos = page.indexOf("<table id=\"tblTravelBugs\"");
if (startPos == -1) {
Log.e(Settings.tag, "cgeoBase.parseTrackableLog: ID \"tblTravelBugs\" not found on page");
return null;
}
page = page.substring(startPos); // cut on <table
endPos = page.indexOf("</table>");
if (endPos == -1) {
Log.e(Settings.tag, "cgeoBase.parseTrackableLog: end of ID \"tblTravelBugs\" not found on page");
return null;
}
page = page.substring(0, endPos); // cut on </table>
startPos = page.indexOf("<tbody>");
if (startPos == -1) {
Log.e(Settings.tag, "cgeoBase.parseTrackableLog: tbody not found on page");
return null;
}
page = page.substring(startPos); // cut on <tbody>
endPos = page.indexOf("</tbody>");
if (endPos == -1) {
Log.e(Settings.tag, "cgeoBase.parseTrackableLog: end of tbody not found on page");
return null;
}
page = page.substring(0, endPos); // cut on </tbody>
final Pattern trackablePattern = Pattern.compile("<tr id=\"ctl00_ContentBody_LogBookPanel1_uxTrackables_repTravelBugs_ctl[0-9]+_row\"[^>]*>"
+ "[^<]*<td>[^<]*<a href=\"[^\"]+\">([A-Z0-9]+)</a>[^<]*</td>[^<]*<td>([^<]+)</td>[^<]*<td>"
+ "[^<]*<select name=\"ctl00\\$ContentBody\\$LogBookPanel1\\$uxTrackables\\$repTravelBugs\\$ctl([0-9]+)\\$ddlAction\"[^>]*>"
+ "([^<]*<option value=\"([0-9]+)(_[a-z]+)?\">[^<]+</option>)+"
+ "[^<]*</select>[^<]*</td>[^<]*</tr>", Pattern.CASE_INSENSITIVE);
final Matcher trackableMatcher = trackablePattern.matcher(page);
while (trackableMatcher.find()) {
if (trackableMatcher.groupCount() > 0) {
final TrackableLog trackable = new TrackableLog();
if (trackableMatcher.group(1) != null) {
trackable.trackCode = trackableMatcher.group(1);
} else {
continue;
}
if (trackableMatcher.group(2) != null) {
trackable.name = Html.fromHtml(trackableMatcher.group(2)).toString();
} else {
continue;
}
if (trackableMatcher.group(3) != null) {
trackable.ctl = new Integer(trackableMatcher.group(3));
} else {
continue;
}
if (trackableMatcher.group(5) != null) {
trackable.id = new Integer(trackableMatcher.group(5));
} else {
continue;
}
Log.i(Settings.tag, "Trackable in inventory (#" + trackable.ctl + "/" + trackable.id + "): " + trackable.trackCode + " - " + trackable.name);
trackables.add(trackable);
}
}
return trackables;
}
public int parseFindCount(String page) {
if (page == null || page.length() == 0) {
return -1;
}
int findCount = -1;
try {
final Pattern findPattern = Pattern.compile("<strong>Caches Found:<\\/strong>([^<]+)<br", Pattern.CASE_INSENSITIVE);
final Matcher findMatcher = findPattern.matcher(page);
if (findMatcher.find() == true) {
if (findMatcher.groupCount() > 0) {
String count = findMatcher.group(1);
if (count != null) {
count = count.trim();
if (count.length() == 0) {
findCount = 0;
} else {
findCount = Integer.parseInt(count);
}
}
}
}
} catch (Exception e) {
Log.w(Settings.tag, "cgBase.parseFindCount: " + e.toString());
}
return findCount;
}
public static String stripParagraphs(String text) {
if (text == null) {
return "";
}
final Pattern patternP = Pattern.compile("(<p>|</p>|<br \\/>|<br>)", Pattern.CASE_INSENSITIVE);
final Pattern patternP2 = Pattern.compile("([ ]+)", Pattern.CASE_INSENSITIVE);
final Matcher matcherP = patternP.matcher(text);
final Matcher matcherP2 = patternP2.matcher(text);
matcherP.replaceAll(" ");
matcherP2.replaceAll(" ");
return text.trim();
}
public static String stripTags(String text) {
if (text == null) {
return "";
}
final Pattern patternP = Pattern.compile("(<[^>]+>)", Pattern.CASE_INSENSITIVE);
final Matcher matcherP = patternP.matcher(text);
matcherP.replaceAll(" ");
return text.trim();
}
public static String capitalizeSentence(String sentence) {
if (sentence == null) {
return "";
}
final String[] word = sentence.split(" ");
for (int i = 0; i < word.length; i++) {
word[i] = capitalizeWord(word[i]);
}
return implode(" ", word);
}
public static String capitalizeWord(String word) {
if (word.length() == 0) {
return word;
}
return (word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase());
}
public static Double parseDistance(String dst) {
Double distance = null;
final Pattern pattern = Pattern.compile("([0-9\\.,]+)[ ]*(km|mi)", Pattern.CASE_INSENSITIVE);
final Matcher matcher = pattern.matcher(dst);
while (matcher.find()) {
if (matcher.groupCount() > 1) {
if (matcher.group(2).equalsIgnoreCase("km") == true) {
distance = new Double(matcher.group(1));
} else {
distance = new Double(matcher.group(1)) / kmInMiles;
}
}
}
return distance;
}
public static double getDistance(Double lat1, Double lon1, Double lat2, Double lon2) {
if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) {
return 0d;
}
lat1 *= deg2rad;
lon1 *= deg2rad;
lat2 *= deg2rad;
lon2 *= deg2rad;
final double d = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2);
final double distance = erad * Math.acos(d); // distance in km
if (Double.isNaN(distance) == false && distance > 0) {
return distance;
} else {
return 0d;
}
}
public static Double getHeading(Double lat1, Double lon1, Double lat2, Double lon2) {
Double result = new Double(0);
int ilat1 = (int) Math.round(0.5 + lat1 * 360000);
int ilon1 = (int) Math.round(0.5 + lon1 * 360000);
int ilat2 = (int) Math.round(0.5 + lat2 * 360000);
int ilon2 = (int) Math.round(0.5 + lon2 * 360000);
lat1 *= deg2rad;
lon1 *= deg2rad;
lat2 *= deg2rad;
lon2 *= deg2rad;
if (ilat1 == ilat2 && ilon1 == ilon2) {
return new Double(result);
} else if (ilat1 == ilat2) {
if (ilon1 > ilon2) {
result = new Double(270);
} else {
result = new Double(90);
}
} else if (ilon1 == ilon2) {
if (ilat1 > ilat2) {
result = new Double(180);
}
} else {
Double c = Math.acos(Math.sin(lat2) * Math.sin(lat1) + Math.cos(lat2) * Math.cos(lat1) * Math.cos(lon2 - lon1));
Double A = Math.asin(Math.cos(lat2) * Math.sin(lon2 - lon1) / Math.sin(c));
result = new Double(A * rad2deg);
if (ilat2 > ilat1 && ilon2 > ilon1) {
// result don't need change
} else if (ilat2 < ilat1 && ilon2 < ilon1) {
result = 180f - result;
} else if (ilat2 < ilat1 && ilon2 > ilon1) {
result = 180f - result;
} else if (ilat2 > ilat1 && ilon2 < ilon1) {
result += 360f;
}
}
return result;
}
public HashMap<String, Double> getRadialDistance(Double latitude, Double longitude, Double bearing, Double distance) {
final Double rlat1 = latitude * deg2rad;
final Double rlon1 = longitude * deg2rad;
final Double rbearing = bearing * deg2rad;
final Double rdistance = distance / erad;
final Double rlat = Math.asin(Math.sin(rlat1) * Math.cos(rdistance) + Math.cos(rlat1) * Math.sin(rdistance) * Math.cos(rbearing));
final Double rlon = rlon1 + Math.atan2(Math.sin(rbearing) * Math.sin(rdistance) * Math.cos(rlat1), Math.cos(rdistance) - Math.sin(rlat1) * Math.sin(rlat));
HashMap<String, Double> result = new HashMap<String, Double>();
result.put("latitude", rlat * rad2deg);
result.put("longitude", rlon * rad2deg);
return result;
}
public String getHumanDistance(Float distance) {
if (distance == null) {
return "?";
}
return getHumanDistance(new Double(distance));
}
public String getHumanDistance(Double distance) {
if (distance == null) {
return "?";
}
if (settings.units == Settings.unitsImperial) {
distance *= kmInMiles;
if (distance > 100) {
return String.format(Locale.getDefault(), "%.0f", new Double(Math.round(distance))) + " mi";
} else if (distance > 0.5) {
return String.format(Locale.getDefault(), "%.1f", new Double(Math.round(distance * 10.0) / 10.0)) + " mi";
} else if (distance > 0.1) {
return String.format(Locale.getDefault(), "%.2f", new Double(Math.round(distance * 100.0) / 100.0)) + " mi";
} else if (distance > 0.05) {
return String.format(Locale.getDefault(), "%.0f", new Double(Math.round(distance * 5280.0))) + " ft";
} else if (distance > 0.01) {
return String.format(Locale.getDefault(), "%.1f", new Double(Math.round(distance * 5280 * 10.0) / 10.0)) + " ft";
} else {
return String.format(Locale.getDefault(), "%.2f", new Double(Math.round(distance * 5280 * 100.0) / 100.0)) + " ft";
}
} else {
if (distance > 100) {
return String.format(Locale.getDefault(), "%.0f", new Double(Math.round(distance))) + " km";
} else if (distance > 10) {
return String.format(Locale.getDefault(), "%.1f", new Double(Math.round(distance * 10.0) / 10.0)) + " km";
} else if (distance > 1) {
return String.format(Locale.getDefault(), "%.2f", new Double(Math.round(distance * 100.0) / 100.0)) + " km";
} else if (distance > 0.1) {
return String.format(Locale.getDefault(), "%.0f", new Double(Math.round(distance * 1000.0))) + " m";
} else if (distance > 0.01) {
return String.format(Locale.getDefault(), "%.1f", new Double(Math.round(distance * 1000.0 * 10.0) / 10.0)) + " m";
} else {
return String.format(Locale.getDefault(), "%.2f", new Double(Math.round(distance * 1000.0 * 100.0) / 100.0)) + " m";
}
}
}
public String getHumanSpeed(float speed) {
double kph = speed * 3.6;
String unit = "kmh";
if (this.settings.units == Settings.unitsImperial) {
kph *= kmInMiles;
unit = "mph";
}
if (kph < 10) {
return String.format(Locale.getDefault(), "%.1f", new Double((Math.round(kph * 10) / 10))) + " " + unit;
} else {
return String.format(Locale.getDefault(), "%.0f", new Double(Math.round(kph))) + " " + unit;
}
}
public HashMap<String, Object> parseLatlon(String latlon) {
final HashMap<String, Object> result = new HashMap<String, Object>();
final Pattern patternLatlon = Pattern.compile("([NS])[^\\d]*(\\d+)[^°]*° (\\d+)\\.(\\d+) ([WE])[^\\d]*(\\d+)[^°]*° (\\d+)\\.(\\d+)", Pattern.CASE_INSENSITIVE);
final Matcher matcherLatlon = patternLatlon.matcher(latlon);
while (matcherLatlon.find()) {
if (matcherLatlon.groupCount() > 0) {
result.put("latitudeString", (String) (matcherLatlon.group(1) + " " + matcherLatlon.group(2) + "° " + matcherLatlon.group(3) + "." + matcherLatlon.group(4)));
result.put("longitudeString", (String) (matcherLatlon.group(5) + " " + matcherLatlon.group(6) + "° " + matcherLatlon.group(7) + "." + matcherLatlon.group(8)));
int latNegative = -1;
int lonNegative = -1;
if (matcherLatlon.group(1).equalsIgnoreCase("N")) {
latNegative = 1;
}
if (matcherLatlon.group(5).equalsIgnoreCase("E")) {
lonNegative = 1;
}
result.put("latitude", new Double(latNegative * (new Float(matcherLatlon.group(2)) + new Float(matcherLatlon.group(3) + "." + matcherLatlon.group(4)) / 60)));
result.put("longitude", new Double(lonNegative * (new Float(matcherLatlon.group(6)) + new Float(matcherLatlon.group(7) + "." + matcherLatlon.group(8)) / 60)));
} else {
Log.w(Settings.tag, "cgBase.parseLatlon: Failed to parse coordinates.");
}
}
return result;
}
public String formatCoordinate(Double coord, String latlon, boolean degrees) {
String formatted = "";
if (coord == null) {
return formatted;
}
String worldSide = "";
if (latlon.equalsIgnoreCase("lat") == true) {
if (coord >= 0) {
// have the blanks here at the direction to avoid one String concatenation
worldSide = "N ";
} else {
worldSide = "S ";
}
} else if (latlon.equalsIgnoreCase("lon") == true) {
if (coord >= 0) {
worldSide = "E ";
} else {
worldSide = "W ";
}
}
coord = Math.abs(coord);
if (latlon.equalsIgnoreCase("lat") == true) {
if (degrees == true) {
formatted = worldSide + String.format(Locale.getDefault(), "%02.0f", Math.floor(coord)) + "° " + String.format(Locale.getDefault(), "%06.3f", ((coord - Math.floor(coord)) * 60));
} else {
formatted = worldSide + String.format(Locale.getDefault(), "%02.0f", Math.floor(coord)) + " " + String.format(Locale.getDefault(), "%06.3f", ((coord - Math.floor(coord)) * 60));
}
} else {
if (degrees == true) {
formatted = worldSide + String.format(Locale.getDefault(), "%03.0f", Math.floor(coord)) + "° " + String.format(Locale.getDefault(), "%06.3f", ((coord - Math.floor(coord)) * 60));
} else {
formatted = worldSide + String.format(Locale.getDefault(), "%03.0f", Math.floor(coord)) + " " + String.format(Locale.getDefault(), "%06.3f", ((coord - Math.floor(coord)) * 60));
}
}
return formatted;
}
public HashMap<String, Object> parseCoordinate(String coord, String latlon) {
final HashMap<String, Object> coords = new HashMap<String, Object>();
final Pattern patternA = Pattern.compile("^([NSWE])[^\\d]*(\\d+)°? +(\\d+)([\\.|,](\\d+))?$", Pattern.CASE_INSENSITIVE);
final Pattern patternB = Pattern.compile("^([NSWE])[^\\d]*(\\d+)([\\.|,](\\d+))?$", Pattern.CASE_INSENSITIVE);
final Pattern patternC = Pattern.compile("^(-?\\d+)([\\.|,](\\d+))?$", Pattern.CASE_INSENSITIVE);
final Pattern patternD = Pattern.compile("^([NSWE])[^\\d]*(\\d+)°?$", Pattern.CASE_INSENSITIVE);
final Pattern patternE = Pattern.compile("^(-?\\d+)°?$", Pattern.CASE_INSENSITIVE);
final Pattern patternF = Pattern.compile("^([NSWE])[^\\d]*(\\d+)$", Pattern.CASE_INSENSITIVE);
final Pattern pattern0 = Pattern.compile("^(-?\\d+)([\\.|,](\\d+))?$", Pattern.CASE_INSENSITIVE);
coord = coord.trim().toUpperCase();
final Matcher matcherA = patternA.matcher(coord);
final Matcher matcherB = patternB.matcher(coord);
final Matcher matcherC = patternC.matcher(coord);
final Matcher matcherD = patternD.matcher(coord);
final Matcher matcherE = patternE.matcher(coord);
final Matcher matcherF = patternF.matcher(coord);
final Matcher matcher0 = pattern0.matcher(coord);
int latlonNegative;
if (matcherA.find() == true && matcherA.groupCount() > 0) {
if (matcherA.group(1).equalsIgnoreCase("N") || matcherA.group(1).equalsIgnoreCase("E")) {
latlonNegative = 1;
} else {
latlonNegative = -1;
}
if (matcherA.groupCount() < 5 || matcherA.group(5) == null) {
coords.put("coordinate", new Double(latlonNegative * (new Double(matcherA.group(2)) + new Double(matcherA.group(3) + ".0") / 60)));
coords.put("string", matcherA.group(1) + " " + matcherA.group(2) + "° " + matcherA.group(3) + ".000");
} else {
coords.put("coordinate", new Double(latlonNegative * (new Double(matcherA.group(2)) + new Double(matcherA.group(3) + "." + matcherA.group(5)) / 60)));
coords.put("string", matcherA.group(1) + " " + matcherA.group(2) + "° " + matcherA.group(3) + "." + matcherA.group(5));
}
return coords;
} else if (matcherB.find() == true && matcherB.groupCount() > 0) {
if (matcherB.group(1).equalsIgnoreCase("N") || matcherB.group(1).equalsIgnoreCase("E")) {
latlonNegative = 1;
} else {
latlonNegative = -1;
}
if (matcherB.groupCount() < 4 || matcherB.group(4) == null) {
coords.put("coordinate", new Double(latlonNegative * (new Double(matcherB.group(2) + ".0"))));
} else {
coords.put("coordinate", new Double(latlonNegative * (new Double(matcherB.group(2) + "." + matcherB.group(4)))));
}
} else if (matcherC.find() == true && matcherC.groupCount() > 0) {
if (matcherC.groupCount() < 3 || matcherC.group(3) == null) {
coords.put("coordinate", new Double(new Float(matcherC.group(1) + ".0")));
} else {
coords.put("coordinate", new Double(new Float(matcherC.group(1) + "." + matcherC.group(3))));
}
} else if (matcherD.find() == true && matcherD.groupCount() > 0) {
if (matcherD.group(1).equalsIgnoreCase("N") || matcherD.group(1).equalsIgnoreCase("E")) {
latlonNegative = 1;
} else {
latlonNegative = -1;
}
coords.put("coordinate", new Double(latlonNegative * (new Double(matcherB.group(2)))));
} else if (matcherE.find() == true && matcherE.groupCount() > 0) {
coords.put("coordinate", new Double(matcherE.group(1)));
} else if (matcherF.find() == true && matcherF.groupCount() > 0) {
if (matcherF.group(1).equalsIgnoreCase("N") || matcherF.group(1).equalsIgnoreCase("E")) {
latlonNegative = 1;
} else {
latlonNegative = -1;
}
coords.put("coordinate", new Double(latlonNegative * (new Double(matcherB.group(2)))));
} else {
return null;
}
if (matcher0.find() == true && matcher0.groupCount() > 0) {
String tmpDir = null;
Float tmpCoord;
if (matcher0.groupCount() < 3 || matcher0.group(3) == null) {
tmpCoord = new Float("0.0");
} else {
tmpCoord = new Float("0." + matcher0.group(3));
}
if (latlon.equalsIgnoreCase("lat")) {
if (matcher0.group(1).equals("+")) {
tmpDir = "N";
}
if (matcher0.group(1).equals("-")) {
tmpDir = "S";
}
} else if (latlon.equalsIgnoreCase("lon")) {
if (matcher0.group(1).equals("+")) {
tmpDir = "E";
}
if (matcher0.group(1).equals("-")) {
tmpDir = "W";
}
}
coords.put("string", tmpDir + " " + matcher0.group(1) + "° " + (Math.round(tmpCoord / (1 / 60) * 1000) * 1000));
return coords;
} else {
return new HashMap<String, Object>();
}
}
public Long searchByNextPage(SearchThread thread, Long searchId, int reason, boolean showCaptcha) {
final String viewstate = app.getViewstate(searchId);
final String viewstate1 = app.getViewstate1(searchId);
CacheWrap caches = new CacheWrap();
String url = app.getUrl(searchId);
if (url == null || url.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByNextPage: No url found");
return searchId;
}
if (viewstate == null || viewstate.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByNextPage: No viewstate given");
return searchId;
}
String host = "www.geocaching.com";
String path = "/";
final String method = "POST";
int dash = -1;
if (url.indexOf("http://") > -1) {
url = url.substring(7);
}
dash = url.indexOf("/");
if (dash > -1) {
host = url.substring(0, dash);
url = url.substring(dash);
} else {
host = url;
url = "";
}
dash = url.indexOf("?");
if (dash > -1) {
path = url.substring(0, dash);
} else {
path = url;
}
final HashMap<String, String> params = new HashMap<String, String>();
params.put("__VIEWSTATE", viewstate);
if (viewstate1 != null) {
params.put("__VIEWSTATE1", viewstate1);
params.put("__VIEWSTATEFIELDCOUNT", "2");
}
params.put("__EVENTTARGET", "ctl00$ContentBody$pgrBottom$ctl08");
params.put("__EVENTARGUMENT", "");
String page = request(false, host, path, method, params, false, false, true).getData();
if (checkLogin(page) == false) {
int loginState = login();
if (loginState == 1) {
page = request(false, host, path, method, params, false, false, true).getData();
} else if (loginState == -3) {
Log.i(Settings.tag, "Working as guest.");
} else {
app.setError(searchId, errorRetrieve.get(loginState));
Log.e(Settings.tag, "cgeoBase.searchByNextPage: Can not log in geocaching");
return searchId;
}
}
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByNextPage: No data from server");
return searchId;
}
caches = parseSearch(thread, url, page, showCaptcha);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
Log.e(Settings.tag, "cgeoBase.searchByNextPage: No cache parsed");
return searchId;
}
// save to Application
app.setError(searchId, caches.error);
app.setViewstate(searchId, caches.viewstate);
app.setViewstate1(searchId, caches.viewstate1);
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
for (Cache cache : caches.cacheList) {
app.addGeocode(searchId, cache.geocode);
cacheList.add(cache);
}
app.addSearch(searchId, cacheList, true, reason);
return searchId;
}
public Long searchByGeocode(HashMap<String, String> parameters, int reason, boolean forceReload) {
final Search search = new Search();
String geocode = parameters.get("geocode");
String guid = parameters.get("guid");
if ((geocode == null || geocode.length() == 0) && ((guid == null || guid.length() == 0))) {
Log.e(Settings.tag, "cgeoBase.searchByGeocode: No geocode nor guid given");
return null;
}
if (forceReload == false && reason == 0 && (app.isOffline(geocode, guid) == true || app.isThere(geocode, guid, true, true) == true)) {
if ((geocode == null || geocode.length() == 0) && guid != null && guid.length() > 0) {
geocode = app.getGeocode(guid);
}
ArrayList<Cache> cacheList = new ArrayList<Cache>();
cacheList.add(app.getCacheByGeocode(geocode, true, true, true, true, true, true));
search.addGeocode(geocode);
app.addSearch(search, cacheList, false, reason);
cacheList.clear();
cacheList = null;
return search.getCurrentId();
}
final String host = "www.geocaching.com";
final String path = "/seek/cache_details.aspx";
final String method = "GET";
final HashMap<String, String> params = new HashMap<String, String>();
if (geocode != null && geocode.length() > 0) {
params.put("wp", geocode);
} else if (guid != null && guid.length() > 0) {
params.put("guid", guid);
}
params.put("decrypt", "y");
params.put("log", "y"); // download logs (more than 5
params.put("numlogs", "35"); // 35 logs
String page = requestLogged(false, host, path, method, params, false, false, false);
if (page == null || page.length() == 0) {
if (app.isThere(geocode, guid, true, false) == true) {
if ((geocode == null || geocode.length() == 0) && guid != null && guid.length() > 0) {
Log.i(Settings.tag, "Loading old cache from cache.");
geocode = app.getGeocode(guid);
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
cacheList.add(app.getCacheByGeocode(geocode));
search.addGeocode(geocode);
search.error = null;
search.errorRetrieve = 0; // reset errors from previous failed request
app.addSearch(search, cacheList, false, reason);
cacheList.clear();
return search.getCurrentId();
}
Log.e(Settings.tag, "cgeoBase.searchByGeocode: No data from server");
return null;
}
final CacheWrap caches = parseCache(page, reason);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
if (caches != null && caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches != null && caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
app.addSearch(search, null, true, reason);
Log.e(Settings.tag, "cgeoBase.searchByGeocode: No cache parsed");
return null;
}
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByGeocode: No application found");
return null;
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
if (caches != null) {
if (caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
if (caches.viewstate != null && caches.viewstate.length() > 0) {
search.viewstate = caches.viewstate;
}
if (caches.viewstate1 != null && caches.viewstate1.length() > 0) {
search.viewstate1 = caches.viewstate1;
}
search.totalCnt = caches.totalCnt;
for (Cache cache : caches.cacheList) {
search.addGeocode(cache.geocode);
cacheList.add(cache);
}
}
app.addSearch(search, cacheList, true, reason);
page = null;
cacheList.clear();
return search.getCurrentId();
}
public Long searchByOffline(HashMap<String, Object> parameters) {
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByOffline: No application found");
return null;
}
Double latitude = null;
Double longitude = null;
String cachetype = null;
Integer list = 1;
if (parameters.containsKey("latitude") == true && parameters.containsKey("longitude") == true) {
latitude = (Double) parameters.get("latitude");
longitude = (Double) parameters.get("longitude");
}
if (parameters.containsKey("cachetype") == true) {
cachetype = (String) parameters.get("cachetype");
}
if (parameters.containsKey("list") == true) {
list = (Integer) parameters.get("list");
}
final Search search = app.getBatchOfStoredCaches(true, latitude, longitude, cachetype, list);
search.totalCnt = app.getAllStoredCachesCount(true, cachetype, list);
return search.getCurrentId();
}
public Long searchByHistory(HashMap<String, Object> parameters) {
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByHistory: No application found");
return null;
}
String cachetype = null;
if (parameters.containsKey("cachetype") == true) {
cachetype = (String) parameters.get("cachetype");
}
final Search search = app.getHistoryOfCaches(true, cachetype);
search.totalCnt = app.getAllHistoricCachesCount(true, cachetype);
return search.getCurrentId();
}
public Long searchByCoords(SearchThread thread, HashMap<String, String> parameters, int reason, boolean showCaptcha) {
final Search search = new Search();
final String latitude = parameters.get("latitude");
final String longitude = parameters.get("longitude");
CacheWrap caches = new CacheWrap();
String cacheType = parameters.get("cachetype");
if (latitude == null || latitude.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No latitude given");
return null;
}
if (longitude == null || longitude.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No longitude given");
return null;
}
if (cacheType != null && cacheType.length() == 0) {
cacheType = null;
}
final String host = "www.geocaching.com";
final String path = "/seek/nearest.aspx";
final String method = "GET";
final HashMap<String, String> params = new HashMap<String, String>();
if (cacheType != null && cacheIDs.containsKey(cacheType) == true) {
params.put("tx", cacheIDs.get(cacheType));
} else {
params.put("tx", cacheIDs.get("all"));
}
params.put("lat", latitude);
params.put("lng", longitude);
final String url = "http://" + host + path + "?" + prepareParameters(params, false, true);
String page = requestLogged(false, host, path, method, params, false, false, true);
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No data from server");
return null;
}
caches = parseSearch(thread, url, page, showCaptcha);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No cache parsed");
}
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No application found");
return null;
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
if (caches != null) {
if (caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
if (caches.viewstate != null && caches.viewstate.length() > 0) {
search.viewstate = caches.viewstate;
}
if (caches.viewstate1 != null && caches.viewstate1.length() > 0) {
search.viewstate1 = caches.viewstate1;
}
search.totalCnt = caches.totalCnt;
for (Cache cache : caches.cacheList) {
if (settings.excludeDisabled == 0 || (settings.excludeDisabled == 1 && cache.disabled == false)) {
search.addGeocode(cache.geocode);
cacheList.add(cache);
}
}
}
app.addSearch(search, cacheList, true, reason);
return search.getCurrentId();
}
public Long searchByKeyword(SearchThread thread, HashMap<String, String> parameters, int reason, boolean showCaptcha) {
final Search search = new Search();
final String keyword = parameters.get("keyword");
CacheWrap caches = new CacheWrap();
String cacheType = parameters.get("cachetype");
if (keyword == null || keyword.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByKeyword: No keyword given");
return null;
}
if (cacheType != null && cacheType.length() == 0) {
cacheType = null;
}
final String host = "www.geocaching.com";
final String path = "/seek/nearest.aspx";
final String method = "GET";
final HashMap<String, String> params = new HashMap<String, String>();
if (cacheType != null && cacheIDs.containsKey(cacheType) == true) {
params.put("tx", cacheIDs.get(cacheType));
} else {
params.put("tx", cacheIDs.get("all"));
}
params.put("key", keyword);
final String url = "http://" + host + path + "?" + prepareParameters(params, false, true);
String page = requestLogged(false, host, path, method, params, false, false, true);
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByKeyword: No data from server");
return null;
}
caches = parseSearch(thread, url, page, showCaptcha);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
Log.e(Settings.tag, "cgeoBase.searchByKeyword: No cache parsed");
}
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No application found");
return null;
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
if (caches != null) {
if (caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
if (caches.viewstate != null && caches.viewstate.length() > 0) {
search.viewstate = caches.viewstate;
}
if (caches.viewstate1 != null && caches.viewstate1.length() > 0) {
search.viewstate1 = caches.viewstate1;
}
search.totalCnt = caches.totalCnt;
for (Cache cache : caches.cacheList) {
if (settings.excludeDisabled == 0 || (settings.excludeDisabled == 1 && cache.disabled == false)) {
search.addGeocode(cache.geocode);
cacheList.add(cache);
}
}
}
app.addSearch(search, cacheList, true, reason);
return search.getCurrentId();
}
public Long searchByUsername(SearchThread thread, HashMap<String, String> parameters, int reason, boolean showCaptcha) {
final Search search = new Search();
final String userName = parameters.get("username");
CacheWrap caches = new CacheWrap();
String cacheType = parameters.get("cachetype");
if (userName == null || userName.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByUsername: No user name given");
return null;
}
if (cacheType != null && cacheType.length() == 0) {
cacheType = null;
}
final String host = "www.geocaching.com";
final String path = "/seek/nearest.aspx";
final String method = "GET";
final HashMap<String, String> params = new HashMap<String, String>();
if (cacheType != null && cacheIDs.containsKey(cacheType) == true) {
params.put("tx", cacheIDs.get(cacheType));
} else {
params.put("tx", cacheIDs.get("all"));
}
params.put("ul", userName);
boolean my = false;
if (userName.equalsIgnoreCase(settings.getLogin().get("username")) == true) {
my = true;
Log.i(Settings.tag, "cgBase.searchByUsername: Overriding users choice, downloading all caches.");
}
final String url = "http://" + host + path + "?" + prepareParameters(params, my, true);
String page = requestLogged(false, host, path, method, params, false, my, true);
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByUsername: No data from server");
return null;
}
caches = parseSearch(thread, url, page, showCaptcha);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
Log.e(Settings.tag, "cgeoBase.searchByUsername: No cache parsed");
}
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No application found");
return null;
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
if (caches != null) {
if (caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
if (caches.viewstate != null && caches.viewstate.length() > 0) {
search.viewstate = caches.viewstate;
}
if (caches.viewstate1 != null && caches.viewstate1.length() > 0) {
search.viewstate1 = caches.viewstate1;
}
search.totalCnt = caches.totalCnt;
for (Cache cache : caches.cacheList) {
if (settings.excludeDisabled == 0 || (settings.excludeDisabled == 1 && cache.disabled == false)) {
search.addGeocode(cache.geocode);
cacheList.add(cache);
}
}
}
app.addSearch(search, cacheList, true, reason);
return search.getCurrentId();
}
public Long searchByOwner(SearchThread thread, HashMap<String, String> parameters, int reason, boolean showCaptcha) {
final Search search = new Search();
final String userName = parameters.get("username");
CacheWrap caches = new CacheWrap();
String cacheType = parameters.get("cachetype");
if (userName == null || userName.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByOwner: No user name given");
return null;
}
if (cacheType != null && cacheType.length() == 0) {
cacheType = null;
}
final String host = "www.geocaching.com";
final String path = "/seek/nearest.aspx";
final String method = "GET";
final HashMap<String, String> params = new HashMap<String, String>();
if (cacheType != null && cacheIDs.containsKey(cacheType) == true) {
params.put("tx", cacheIDs.get(cacheType));
} else {
params.put("tx", cacheIDs.get("all"));
}
params.put("u", userName);
final String url = "http://" + host + path + "?" + prepareParameters(params, false, true);
String page = requestLogged(false, host, path, method, params, false, false, true);
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByOwner: No data from server");
return null;
}
caches = parseSearch(thread, url, page, showCaptcha);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
Log.e(Settings.tag, "cgeoBase.searchByOwner: No cache parsed");
}
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByCoords: No application found");
return null;
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
if (caches != null) {
if (caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
if (caches.viewstate != null && caches.viewstate.length() > 0) {
search.viewstate = caches.viewstate;
}
if (caches.viewstate1 != null && caches.viewstate1.length() > 0) {
search.viewstate1 = caches.viewstate1;
}
search.totalCnt = caches.totalCnt;
for (Cache cache : caches.cacheList) {
if (settings.excludeDisabled == 0 || (settings.excludeDisabled == 1 && cache.disabled == false)) {
search.addGeocode(cache.geocode);
cacheList.add(cache);
}
}
}
app.addSearch(search, cacheList, true, reason);
return search.getCurrentId();
}
public Long searchByViewport(HashMap<String, String> parameters, int reason) {
final Search search = new Search();
final String latMin = parameters.get("latitude-min");
final String latMax = parameters.get("latitude-max");
final String lonMin = parameters.get("longitude-min");
final String lonMax = parameters.get("longitude-max");
String usertoken = null;
if (parameters.get("usertoken") != null) {
usertoken = parameters.get("usertoken");
} else {
usertoken = "";
}
CacheWrap caches = new CacheWrap();
String page = null;
if (latMin == null || latMin.length() == 0 || latMax == null || latMax.length() == 0 || lonMin == null || lonMin.length() == 0 || lonMax == null || lonMax.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByViewport: Not enough parameters to recognize viewport");
return null;
}
final String host = "www.geocaching.com";
final String path = "/map/default.aspx/MapAction";
String params = "{\"dto\":{\"data\":{\"c\":1,\"m\":\"\",\"d\":\"" + latMax + "|" + latMin + "|" + lonMax + "|" + lonMin + "\"},\"ut\":\"" + usertoken + "\"}}";
final String url = "http://" + host + path + "?" + params;
page = requestJSONgc(host, path, params);
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchByViewport: No data from server");
return null;
}
caches = parseMapJSON(url, page);
if (caches == null || caches.cacheList == null || caches.cacheList.isEmpty()) {
Log.e(Settings.tag, "cgeoBase.searchByViewport: No cache parsed");
}
if (app == null) {
Log.e(Settings.tag, "cgeoBase.searchByViewport: No application found");
return null;
}
final ArrayList<Cache> cacheList = new ArrayList<Cache>();
if (caches != null) {
if (caches.error != null && caches.error.length() > 0) {
search.error = caches.error;
}
if (caches.url != null && caches.url.length() > 0) {
search.url = caches.url;
}
if (caches.viewstate != null && caches.viewstate.length() > 0) {
search.viewstate = caches.viewstate;
}
if (caches.viewstate1 != null && caches.viewstate1.length() > 0) {
search.viewstate1 = caches.viewstate1;
}
search.totalCnt = caches.totalCnt;
if (caches.cacheList != null && caches.cacheList.size() > 0) {
for (Cache cache : caches.cacheList) {
if ((settings.excludeDisabled == 0 || (settings.excludeDisabled == 1 && cache.disabled == false))
&& (settings.excludeMine == 0 || (settings.excludeMine == 1 && cache.own == false))
&& (settings.excludeMine == 0 || (settings.excludeMine == 1 && cache.found == false))
&& (settings.cacheType == null || (settings.cacheType.equals(cache.type) == true))) {
search.addGeocode(cache.geocode);
cacheList.add(cache);
}
}
}
}
app.addSearch(search, cacheList, true, reason);
return search.getCurrentId();
}
public ArrayList<User> getGeocachersInViewport(String username, Double latMin, Double latMax, Double lonMin, Double lonMax) {
final ArrayList<User> users = new ArrayList<User>();
if (username == null) {
return users;
}
if (latMin == null || latMax == null || lonMin == null || lonMax == null) {
return users;
}
final String host = "api.go4cache.com";
final String path = "/get.php";
final String method = "POST";
final HashMap<String, String> params = new HashMap<String, String>();
params.put("u", username);
params.put("ltm", String.format((Locale) null, "%.6f", latMin));
params.put("ltx", String.format((Locale) null, "%.6f", latMax));
params.put("lnm", String.format((Locale) null, "%.6f", lonMin));
params.put("lnx", String.format((Locale) null, "%.6f", lonMax));
final String data = request(false, host, path, method, params, false, false, false).getData();
if (data == null || data.length() == 0) {
Log.e(Settings.tag, "cgeoBase.getGeocachersInViewport: No data from server");
return null;
}
try {
final JSONObject dataJSON = new JSONObject(data);
final JSONArray usersData = dataJSON.getJSONArray("users");
if (usersData != null && usersData.length() > 0) {
int count = usersData.length();
JSONObject oneUser = null;
for (int i = 0; i < count; i++) {
final User user = new User();
oneUser = usersData.getJSONObject(i);
if (oneUser != null) {
final String located = oneUser.getString("located");
if (located != null) {
user.located = dateSqlIn.parse(located);
} else {
user.located = new Date();
}
user.username = oneUser.getString("user");
user.latitude = oneUser.getDouble("latitude");
user.longitude = oneUser.getDouble("longitude");
user.action = oneUser.getString("action");
user.client = oneUser.getString("client");
if (user.latitude != null && user.longitude != null) {
users.add(user);
}
}
}
}
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.getGeocachersInViewport: " + e.toString());
}
return users;
}
public Trackable searchTrackable(HashMap<String, String> parameters) {
final String geocode = parameters.get("geocode");
final String guid = parameters.get("guid");
final String id = parameters.get("id");
Trackable trackable = new Trackable();
if ((geocode == null || geocode.length() == 0) && (guid == null || guid.length() == 0) && (id == null || id.length() == 0)) {
Log.e(Settings.tag, "cgeoBase.searchTrackable: No geocode nor guid nor id given");
return null;
}
final String host = "www.geocaching.com";
final String path = "/track/details.aspx";
final String method = "GET";
final HashMap<String, String> params = new HashMap<String, String>();
if (geocode != null && geocode.length() > 0) {
params.put("tracker", geocode);
} else if (guid != null && guid.length() > 0) {
params.put("guid", guid);
} else if (id != null && id.length() > 0) {
params.put("id", id);
}
String page = requestLogged(false, host, path, method, params, false, false, false);
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.searchTrackable: No data from server");
return trackable;
}
trackable = parseTrackable(page);
if (trackable == null) {
Log.e(Settings.tag, "cgeoBase.searchTrackable: No trackable parsed");
return trackable;
}
return trackable;
}
public int postLog(App app, String geocode, String cacheid, String viewstate, String viewstate1, int logType, int year, int month, int day, String log, ArrayList<TrackableLog> trackables) {
if (viewstate == null || viewstate.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLog: No viewstate given");
return 1000;
}
if (logTypes2.containsKey(logType) == false) {
Log.e(Settings.tag, "cgeoBase.postLog: Unknown logtype");
return 1000;
}
if (log == null || log.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLog: No log text given");
return 1001;
}
// 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((int) c));
logUpdated.append(";");
} else {
logUpdated.append(c);
}
}
log = logUpdated.toString();
log = log.replace("\n", "\r\n"); // windows' eol
if (trackables != null) {
Log.i(Settings.tag, "Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + log + "; trackables: " + trackables.size());
} else {
Log.i(Settings.tag, "Trying to post log for cache #" + cacheid + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + log + "; trackables: 0");
}
final String host = "www.geocaching.com";
final String path = "/seek/log.aspx?ID=" + cacheid;
final String method = "POST";
final HashMap<String, String> params = new HashMap<String, String>();
params.put("__VIEWSTATE", viewstate);
if (viewstate1 != null) {
params.put("__VIEWSTATE1", viewstate1);
params.put("__VIEWSTATEFIELDCOUNT", "2");
}
params.put("__EVENTTARGET", "");
params.put("__EVENTARGUMENT", "");
params.put("__LASTFOCUS", "");
params.put("ctl00$ContentBody$LogBookPanel1$ddLogType", Integer.toString(logType));
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged", String.format("%02d", month) + "/" + String.format("%02d", day) + "/" + String.format("%04d", year));
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Month", Integer.toString(month));
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Day", Integer.toString(day));
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Year", Integer.toString(year));
params.put("ctl00$ContentBody$LogBookPanel1$uxLogInfo", log);
params.put("ctl00$ContentBody$LogBookPanel1$LogButton", "Submit Log Entry");
params.put("ctl00$ContentBody$uxVistOtherListingGC", "");
if (trackables != null && trackables.isEmpty() == false) { // we have some trackables to proceed
final StringBuilder hdnSelected = new StringBuilder();
for (TrackableLog tb : trackables) {
final String action = Integer.toString(tb.id) + logTypesTrackableAction.get(tb.action);
if (tb.action > 0) {
hdnSelected.append(action);
hdnSelected.append(",");
}
}
params.put("ctl00$ContentBody$LogBookPanel1$uxTrackables$hdnSelectedActions", hdnSelected.toString()); // selected trackables
params.put("ctl00$ContentBody$LogBookPanel1$uxTrackables$hdnCurrentFilter", "");
}
String page = request(false, host, path, method, params, false, false, false).getData();
if (checkLogin(page) == false) {
int loginState = login();
if (loginState == 1) {
page = request(false, host, path, method, params, false, false, false).getData();
} else {
Log.e(Settings.tag, "cgeoBase.postLog: Can not log in geocaching (error: " + loginState + ")");
return loginState;
}
}
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLog: No data from server");
return 1002;
}
// maintenance, archived needs to be confirmed
final Pattern pattern = Pattern.compile("<span id=\"ctl00_ContentBody_LogBookPanel1_lbConfirm\"[^>]*>([^<]*<font[^>]*>)?([^<]+)(</font>[^<]*)?</span>", Pattern.CASE_INSENSITIVE);
final Matcher matcher = pattern.matcher(page);
try {
if (matcher.find() == true && matcher.groupCount() > 0) {
final String viewstateConfirm = findViewstate(page, 0);
final String viewstate1Confirm = findViewstate(page, 1);
if (viewstateConfirm == null || viewstateConfirm.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLog: No viewstate for confirm log");
return 1000;
}
params.clear();
params.put("__VIEWSTATE", viewstateConfirm);
if (viewstate1 != null) {
params.put("__VIEWSTATE1", viewstate1Confirm);
params.put("__VIEWSTATEFIELDCOUNT", "2");
}
params.put("__EVENTTARGET", "");
params.put("__EVENTARGUMENT", "");
params.put("__LASTFOCUS", "");
params.put("ctl00$ContentBody$LogBookPanel1$btnConfirm", "Yes");
params.put("ctl00$ContentBody$LogBookPanel1$uxLogInfo", log);
params.put("ctl00$ContentBody$uxVistOtherListingGC", "");
if (trackables != null && trackables.isEmpty() == false) { // we have some trackables to proceed
final StringBuilder hdnSelected = new StringBuilder();
for (TrackableLog tb : trackables) {
String ctl = null;
final String action = Integer.toString(tb.id) + logTypesTrackableAction.get(tb.action);
if (tb.ctl < 10) {
ctl = "0" + Integer.toString(tb.ctl);
} else {
ctl = Integer.toString(tb.ctl);
}
params.put("ctl00$ContentBody$LogBookPanel1$uxTrackables$repTravelBugs$ctl" + ctl + "$ddlAction", action);
if (tb.action > 0) {
hdnSelected.append(action);
hdnSelected.append(",");
}
}
params.put("ctl00$ContentBody$LogBookPanel1$uxTrackables$hdnSelectedActions", hdnSelected.toString()); // selected trackables
params.put("ctl00$ContentBody$LogBookPanel1$uxTrackables$hdnCurrentFilter", "");
}
page = request(false, host, path, method, params, false, false, false).getData();
}
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.postLog.confim: " + e.toString());
}
try {
final Pattern patternOk = Pattern.compile("<h2[^>]*>[^<]*<span id=\"ctl00_ContentBody_lbHeading\"[^>]*>[^<]*</span>[^<]*</h2>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Matcher matcherOk = patternOk.matcher(page);
if (matcherOk.find() == true) {
Log.i(Settings.tag, "Log successfully posted to cache #" + cacheid);
if (app != null && geocode != null) {
app.saveVisitDate(geocode);
}
return 1;
}
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.postLog.check: " + e.toString());
}
Log.e(Settings.tag, "cgeoBase.postLog: Failed to post log because of unknown error");
return 1000;
}
public int postLogTrackable(String tbid, String trackingCode, String viewstate, String viewstate1, int logType, int year, int month, int day, String log) {
if (viewstate == null || viewstate.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLogTrackable: No viewstate given");
return 1000;
}
if (logTypes2.containsKey(logType) == false) {
Log.e(Settings.tag, "cgeoBase.postLogTrackable: Unknown logtype");
return 1000;
}
if (log == null || log.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLogTrackable: No log text given");
return 1001;
}
Log.i(Settings.tag, "Trying to post log for trackable #" + trackingCode + " - action: " + logType + "; date: " + year + "." + month + "." + day + ", log: " + log);
log = log.replace("\n", "\r\n"); // windows' eol
final Calendar currentDate = Calendar.getInstance();
final String host = "www.geocaching.com";
final String path = "/track/log.aspx?wid=" + tbid;
final String method = "POST";
final HashMap<String, String> params = new HashMap<String, String>();
params.put("__VIEWSTATE", viewstate);
if (viewstate1 != null) {
params.put("__VIEWSTATE1", viewstate1);
params.put("__VIEWSTATEFIELDCOUNT", "2");
}
params.put("__EVENTTARGET", "");
params.put("__EVENTARGUMENT", "");
params.put("__LASTFOCUS", "");
params.put("ctl00$ContentBody$LogBookPanel1$ddLogType", Integer.toString(logType));
params.put("ctl00$ContentBody$LogBookPanel1$tbCode", trackingCode);
if (currentDate.get(Calendar.YEAR) == year && (currentDate.get(Calendar.MONTH) + 1) == month && currentDate.get(Calendar.DATE) == day) {
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged", "");
} else {
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged", Integer.toString(month) + "/" + Integer.toString(day) + "/" + Integer.toString(year));
}
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Day", Integer.toString(day));
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Month", Integer.toString(month));
params.put("ctl00$ContentBody$LogBookPanel1$DateTimeLogged$Year", Integer.toString(year));
params.put("ctl00$ContentBody$LogBookPanel1$uxLogInfo", log);
params.put("ctl00$ContentBody$LogBookPanel1$LogButton", "Submit Log Entry");
params.put("ctl00$ContentBody$uxVistOtherListingGC", "");
String page = request(false, host, path, method, params, false, false, false).getData();
if (checkLogin(page) == false) {
int loginState = login();
if (loginState == 1) {
page = request(false, host, path, method, params, false, false, false).getData();
} else {
Log.e(Settings.tag, "cgeoBase.postLogTrackable: Can not log in geocaching (error: " + loginState + ")");
return loginState;
}
}
if (page == null || page.length() == 0) {
Log.e(Settings.tag, "cgeoBase.postLogTrackable: No data from server");
return 1002;
}
try {
final Pattern patternOk = Pattern.compile("<div id=[\"|']ctl00_ContentBody_LogBookPanel1_ViewLogPanel[\"|']>", Pattern.CASE_INSENSITIVE);
final Matcher matcherOk = patternOk.matcher(page);
if (matcherOk.find() == true) {
Log.i(Settings.tag, "Log successfully posted to trackable #" + trackingCode);
return 1;
}
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.postLogTrackable.check: " + e.toString());
}
Log.e(Settings.tag, "cgeoBase.postLogTrackable: Failed to post log because of unknown error");
return 1000;
}
final public static HostnameVerifier doNotVerify = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
public static void trustAllHosts() {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
};
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.trustAllHosts: " + e.toString());
}
}
private void readIntoBuffer(BufferedReader br, StringBuffer buffer) throws IOException {
int bufferSize = 1024*16;
char[] bytes = new char[bufferSize];
int bytesRead;
while ((bytesRead = br.read(bytes)) > 0) {
if (bytesRead == bufferSize) {
buffer.append(bytes);
}
else {
buffer.append(bytes, 0, bytesRead);
}
}
}
/*
public ArrayList<String> translate(ArrayList<String> text, String target) {
if (settings.translate == false) {
return text;
}
String[] languages = null;
if (settings.languages != null) {
languages = settings.languages.split(" ");
}
ArrayList<String> translated = new ArrayList<String>();
String language = null;
if (text == null || text.isEmpty()) {
return text;
}
// cut to 5000 characters (limitation of Google Translation API)
for (String textOne : text) {
int len = urlencode_rfc3986(textOne).length();
if (len > 5000) {
textOne = Html.fromHtml(textOne).toString();
len = urlencode_rfc3986(textOne).length();
if (len > 5000) {
int cut = 2000;
if (textOne.length() > cut) {
cut = 1000;
}
textOne = textOne.substring(0, cut) + "...";
}
}
}
try {
if (target == null) {
final Locale locale = Locale.getDefault();
target = locale.getLanguage();
}
final String scheme = "https://";
final String host = "www.googleapis.com";
final String path = "/language/translate/v2";
final ArrayList<String> params = new ArrayList<String>();
params.add("key=" + urlencode_rfc3986("AIzaSyAJH8x5etFHUbFifmgChlWoCVmwBFSwShQ"));
params.add("target=" + urlencode_rfc3986(target));
for (String textOne : text) {
params.add("q=" + urlencode_rfc3986(textOne));
}
params.add("format=" + urlencode_rfc3986("html"));
String page = requestJSON(scheme, host, path, "POST", implode("&", params.toArray()));
if (page == null || page.length() == 0) {
return text;
}
JSONObject json = new JSONObject(page);
JSONObject jsonData = json.getJSONObject("data");
JSONArray jsonTranslations = jsonData.getJSONArray("translations");
int translationCnt = jsonTranslations.length();
for (int i = 0; i < translationCnt; i ++) {
JSONObject jsonTranslation = jsonTranslations.getJSONObject(i);
language = jsonTranslation.getString("detectedSourceLanguage");
boolean toTranslate = true;
if (languages != null) {
for (String lng : languages) {
if (lng.equalsIgnoreCase(language)) {
toTranslate = false;
}
}
}
if (toTranslate == false) {
translated.add(text.get(i));
} else {
Log.i(Settings.tag, "Translating #" + i + ": " + language + ">" + target);
translated.add(jsonTranslation.getString("translatedText"));
}
}
} catch (Exception e) {
Log.w(Settings.tag, "Base.translate: " + e.toString());
}
return translated;
}
*/
public String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException e) {
// nothing
}
return null;
}
public static String implode(String delim, Object[] array) {
String out = "";
try {
for (int i = 0; i < array.length; i++) {
if (i != 0) {
out += delim;
}
out += array[i].toString();
}
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.implode: " + e.toString());
}
return out;
}
public static String urlencode_rfc3986(String text) {
final String encoded = URLEncoder.encode(text).replace("+", "%20").replaceAll("%7E", "~");
return encoded;
}
public String prepareParameters(HashMap<String, String> params, boolean my, boolean addF) {
String paramsDone = null;
if (my != true && settings.excludeMine > 0) {
if (params == null) {
params = new HashMap<String, String>();
}
if (addF == true) {
params.put("f", "1");
}
Log.i(Settings.tag, "Skipping caches found or hidden by user.");
}
if (params != null) {
Object[] keys = params.keySet().toArray();
ArrayList<String> paramsEncoded = new ArrayList<String>();
String key;
String value;
for (int i = 0; i < keys.length; i++) {
key = (String) keys[i];
value = (String) params.get(key);
if (key.charAt(0) == '^') {
key = "";
}
if (value == null) {
value = "";
}
paramsEncoded.add(key + "=" + urlencode_rfc3986(value));
}
paramsDone = implode("&", paramsEncoded.toArray());
} else {
paramsDone = "";
}
return paramsDone;
}
public String requestViewstate(boolean secure, String host, String path, String method, HashMap<String, String> params, boolean xContentType, boolean my) {
final Response response = request(secure, host, path, method, params, xContentType, my, false);
return findViewstate(response.getData(), 0);
}
public String requestViewstate1(boolean secure, String host, String path, String method, HashMap<String, String> params, boolean xContentType, boolean my) {
final Response response = request(secure, host, path, method, params, xContentType, my, false);
return findViewstate(response.getData(), 1);
}
public String requestLogged(boolean secure, String host, String path, String method, HashMap<String, String> params, boolean xContentType, boolean my, boolean addF) {
Response response = request(secure, host, path, method, params, xContentType, my, addF);
String data = response.getData();
if (checkLogin(data) == false) {
int loginState = login();
if (loginState == 1) {
response = request(secure, host, path, method, params, xContentType, my, addF);
data = response.getData();
} else {
Log.i(Settings.tag, "Working as guest.");
}
}
return data;
}
public Response request(boolean secure, String host, String path, String method, HashMap<String, String> params, boolean xContentType, boolean my, boolean addF) {
// prepare parameters
final String paramsDone = prepareParameters(params, my, addF);
return request(secure, host, path, method, paramsDone, 0, xContentType);
}
public Response request(boolean secure, String host, String path, String method, HashMap<String, String> params, int requestId, boolean xContentType, boolean my, boolean addF) {
// prepare parameters
final String paramsDone = prepareParameters(params, my, addF);
return request(secure, host, path, method, paramsDone, requestId, xContentType);
}
public Response request(boolean secure, String host, String path, String method, String params, int requestId, Boolean xContentType) {
URL u = null;
int httpCode = -1;
String httpMessage = null;
String httpLocation = null;
if (requestId == 0) {
requestId = (int) (Math.random() * 1000);
}
if (method == null || (method.equalsIgnoreCase("GET") == false && method.equalsIgnoreCase("POST") == false)) {
method = "POST";
} else {
method = method.toUpperCase();
}
// https
String scheme = "http://";
if (secure) {
scheme = "https://";
}
// prepare cookies
String cookiesDone = null;
if (cookies == null || cookies.isEmpty() == true) {
if (cookies == null) {
cookies = new HashMap<String, String>();
}
final Map<String, ?> prefsAll = prefs.getAll();
final Set<String> prefsKeys = prefsAll.keySet();
for (String key : prefsKeys) {
if (key.matches("cookie_.+") == true) {
final String cookieKey = key.substring(7);
final String cookieValue = (String) prefsAll.get(key);
cookies.put(cookieKey, cookieValue);
}
}
}
if (cookies != null && !cookies.isEmpty() && cookies.keySet().size() > 0) {
final Object[] keys = cookies.keySet().toArray();
final ArrayList<String> cookiesEncoded = new ArrayList<String>();
for (int i = 0; i < keys.length; i++) {
String value = cookies.get(keys[i].toString());
cookiesEncoded.add(keys[i] + "=" + value);
}
if (cookiesEncoded.size() > 0) {
cookiesDone = implode("; ", cookiesEncoded.toArray());
}
}
if (cookiesDone == null) {
Map<String, ?> prefsValues = prefs.getAll();
if (prefsValues != null && prefsValues.size() > 0 && prefsValues.keySet().size() > 0) {
final Object[] keys = prefsValues.keySet().toArray();
final ArrayList<String> cookiesEncoded = new ArrayList<String>();
final int length = keys.length;
for (int i = 0; i < length; i++) {
if (keys[i].toString().length() > 7 && keys[i].toString().substring(0, 7).equals("cookie_") == true) {
cookiesEncoded.add(keys[i].toString().substring(7) + "=" + prefsValues.get(keys[i].toString()));
}
}
if (cookiesEncoded.size() > 0) {
cookiesDone = implode("; ", cookiesEncoded.toArray());
}
}
}
if (cookiesDone == null) {
cookiesDone = "";
}
URLConnection uc = null;
HttpURLConnection connection = null;
Integer timeout = 30000;
StringBuffer buffer = null;
for (int i = 0; i < 5; i++) {
if (i > 0) {
Log.w(Settings.tag, "Failed to download data, retrying. Attempt #" + (i + 1));
}
buffer = new StringBuffer();
timeout = 30000 + (i * 10000);
try {
if (method.equals("GET")) {
// GET
u = new URL(scheme + host + path + "?" + params);
uc = u.openConnection();
uc.setRequestProperty("Host", host);
uc.setRequestProperty("Cookie", cookiesDone);
if (xContentType == true) {
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
}
if (settings.asBrowser == 1) {
uc.setRequestProperty("Accept", "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
// uc.setRequestProperty("Accept-Encoding", "gzip"); // not supported via cellular network
uc.setRequestProperty("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");
uc.setRequestProperty("Accept-Language", "en-US");
uc.setRequestProperty("User-Agent", idBrowser);
uc.setRequestProperty("Connection", "keep-alive");
uc.setRequestProperty("Keep-Alive", "300");
}
connection = (HttpURLConnection) uc;
connection.setReadTimeout(timeout);
connection.setRequestMethod(method);
HttpURLConnection.setFollowRedirects(false);
connection.setDoInput(true);
connection.setDoOutput(false);
} else {
// POST
u = new URL(scheme + host + path);
uc = u.openConnection();
uc.setRequestProperty("Host", host);
uc.setRequestProperty("Cookie", cookiesDone);
if (xContentType == true) {
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
}
if (settings.asBrowser == 1) {
uc.setRequestProperty("Accept", "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
// uc.setRequestProperty("Accept-Encoding", "gzip"); // not supported via cellular network
uc.setRequestProperty("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");
uc.setRequestProperty("Accept-Language", "en-US");
uc.setRequestProperty("User-Agent", idBrowser);
uc.setRequestProperty("Connection", "keep-alive");
uc.setRequestProperty("Keep-Alive", "300");
}
connection = (HttpURLConnection) uc;
connection.setReadTimeout(timeout);
connection.setRequestMethod(method);
HttpURLConnection.setFollowRedirects(false);
connection.setDoInput(true);
connection.setDoOutput(true);
final OutputStream out = connection.getOutputStream();
final OutputStreamWriter wr = new OutputStreamWriter(out);
wr.write(params);
wr.flush();
wr.close();
}
String headerName = null;
final SharedPreferences.Editor prefsEditor = prefs.edit();
for (int j = 1; (headerName = uc.getHeaderFieldKey(j)) != null; j++) {
if (headerName != null && headerName.equalsIgnoreCase("Set-Cookie")) {
int index;
String cookie = uc.getHeaderField(j);
index = cookie.indexOf(";");
if (index > -1) {
cookie = cookie.substring(0, cookie.indexOf(";"));
}
index = cookie.indexOf("=");
if (index > - 1 && cookie.length() > (index + 1)) {
String name = cookie.substring(0, cookie.indexOf("="));
String value = cookie.substring(cookie.indexOf("=") + 1, cookie.length());
cookies.put(name, value);
prefsEditor.putString("cookie_" + name, value);
}
}
}
prefsEditor.commit();
final String encoding = connection.getContentEncoding();
InputStream ins;
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
ins = new GZIPInputStream(connection.getInputStream());
} else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
ins = new InflaterInputStream(connection.getInputStream(), new Inflater(true));
} else {
ins = connection.getInputStream();
}
final InputStreamReader inr = new InputStreamReader(ins);
final BufferedReader br = new BufferedReader(inr);
readIntoBuffer(br, buffer);
httpCode = connection.getResponseCode();
httpMessage = connection.getResponseMessage();
httpLocation = uc.getHeaderField("Location");
final String paramsLog = params.replaceAll(passMatch, "password=***");
if (buffer != null && connection != null) {
Log.i(Settings.tag + "|" + requestId, "[" + method + " " + (int)(params.length() / 1024) + "k | " + httpCode + " | " + (int)(buffer.length() / 1024) + "k] Downloaded " + scheme + host + path + "?" + paramsLog);
} else {
Log.i(Settings.tag + "|" + requestId, "[" + method + " | " + httpCode + "] Failed to download " + scheme + host + path + "?" + paramsLog);
}
connection.disconnect();
br.close();
ins.close();
inr.close();
} catch (IOException e) {
Log.e(Settings.tag, "cgeoBase.request.IOException: " + e.toString());
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.request: " + e.toString());
}
if (buffer != null && buffer.length() > 0) {
break;
}
}
Response response = new Response();
String data = null;
try {
if (httpCode == 302 && httpLocation != null) {
final Uri newLocation = Uri.parse(httpLocation);
if (newLocation.isRelative() == true) {
response = request(secure, host, path, "GET", new HashMap<String, String>(), requestId, false, false, false);
} else {
boolean secureRedir = false;
if (newLocation.getScheme().equals("https")) {
secureRedir = true;
}
response = request(secureRedir, newLocation.getHost(), newLocation.getPath(), "GET", new HashMap<String, String>(), requestId, false, false, false);
}
} else {
if (buffer != null && buffer.length() > 0) {
data = replaceWhitespace(buffer);
buffer = null;
if (data != null) {
response.setData(data);
} else {
response.setData("");
}
response.setStatusCode(httpCode);
response.setStatusMessage(httpMessage);
response.setUrl(u.toString());
}
}
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.page: " + e.toString());
}
return response;
}
private String replaceWhitespace(final StringBuffer buffer) {
final int length = buffer.length();
final char[] bytes = new char[length];
buffer.getChars(0, length, bytes, 0);
int resultSize = 0;
boolean lastWasWhitespace = false;
for (int i = 0; i < length; i++) {
char c = bytes[i];
if (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
if (!lastWasWhitespace) {
bytes[resultSize++] =' ';
}
lastWasWhitespace = true;
} else {
bytes[resultSize++] = c;
lastWasWhitespace = false;
}
}
return new String(bytes, 0, resultSize);
}
public String requestJSONgc(String host, String path, String params) {
int httpCode = -1;
String httpLocation = null;
// prepare cookies
String cookiesDone = null;
if (cookies == null || cookies.isEmpty() == true) {
if (cookies == null) {
cookies = new HashMap<String, String>();
}
final Map<String, ?> prefsAll = prefs.getAll();
final Set<String> prefsKeys = prefsAll.keySet();
for (String key : prefsKeys) {
if (key.matches("cookie_.+") == true) {
final String cookieKey = key.substring(7);
final String cookieValue = (String) prefsAll.get(key);
cookies.put(cookieKey, cookieValue);
}
}
}
if (cookies != null) {
final Object[] keys = cookies.keySet().toArray();
final ArrayList<String> cookiesEncoded = new ArrayList<String>();
for (int i = 0; i < keys.length; i++) {
String value = cookies.get(keys[i].toString());
cookiesEncoded.add(keys[i] + "=" + value);
}
if (cookiesEncoded.size() > 0) {
cookiesDone = implode("; ", cookiesEncoded.toArray());
}
}
if (cookiesDone == null) {
Map<String, ?> prefsValues = prefs.getAll();
if (prefsValues != null && prefsValues.size() > 0) {
final Object[] keys = prefsValues.keySet().toArray();
final ArrayList<String> cookiesEncoded = new ArrayList<String>();
final int length = keys.length;
for (int i = 0; i < length; i++) {
if (keys[i].toString().length() > 7 && keys[i].toString().substring(0, 7).equals("cookie_") == true) {
cookiesEncoded.add(keys[i].toString().substring(7) + "=" + prefsValues.get(keys[i].toString()));
}
}
if (cookiesEncoded.size() > 0) {
cookiesDone = implode("; ", cookiesEncoded.toArray());
}
}
}
if (cookiesDone == null) {
cookiesDone = "";
}
URLConnection uc = null;
HttpURLConnection connection = null;
Integer timeout = 30000;
final StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 3; i++) {
if (i > 0) {
Log.w(Settings.tag, "Failed to download data, retrying. Attempt #" + (i + 1));
}
buffer.delete(0, buffer.length());
timeout = 30000 + (i * 15000);
try {
// POST
final URL u = new URL("http://" + host + path);
uc = u.openConnection();
uc.setRequestProperty("Host", host);
uc.setRequestProperty("Cookie", cookiesDone);
uc.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
uc.setRequestProperty("X-Requested-With", "XMLHttpRequest");
uc.setRequestProperty("Accept", "application/json, text/javascript, */*; q=0.01");
uc.setRequestProperty("Referer", host + "/" + path);
if (settings.asBrowser == 1) {
uc.setRequestProperty("Accept-Charset", "utf-8, iso-8859-1, utf-16, *;q=0.7");
uc.setRequestProperty("Accept-Language", "en-US");
uc.setRequestProperty("User-Agent", idBrowser);
uc.setRequestProperty("Connection", "keep-alive");
uc.setRequestProperty("Keep-Alive", "300");
}
connection = (HttpURLConnection) uc;
connection.setReadTimeout(timeout);
connection.setRequestMethod("POST");
HttpURLConnection.setFollowRedirects(false); // TODO: Fix these (FilCab)
connection.setDoInput(true);
connection.setDoOutput(true);
final OutputStream out = connection.getOutputStream();
final OutputStreamWriter wr = new OutputStreamWriter(out);
wr.write(params);
wr.flush();
wr.close();
String headerName = null;
final SharedPreferences.Editor prefsEditor = prefs.edit();
for (int j = 1; (headerName = uc.getHeaderFieldKey(j)) != null; j++) {
if (headerName != null && headerName.equalsIgnoreCase("Set-Cookie")) {
int index;
String cookie = uc.getHeaderField(j);
index = cookie.indexOf(";");
if (index > -1) {
cookie = cookie.substring(0, cookie.indexOf(";"));
}
index = cookie.indexOf("=");
if (index > - 1 && cookie.length() > (index + 1)) {
String name = cookie.substring(0, cookie.indexOf("="));
String value = cookie.substring(cookie.indexOf("=") + 1, cookie.length());
cookies.put(name, value);
prefsEditor.putString("cookie_" + name, value);
}
}
}
prefsEditor.commit();
final String encoding = connection.getContentEncoding();
InputStream ins;
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
ins = new GZIPInputStream(connection.getInputStream());
} else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
ins = new InflaterInputStream(connection.getInputStream(), new Inflater(true));
} else {
ins = connection.getInputStream();
}
final InputStreamReader inr = new InputStreamReader(ins);
final BufferedReader br = new BufferedReader(inr);
readIntoBuffer(br, buffer);
httpCode = connection.getResponseCode();
httpLocation = uc.getHeaderField("Location");
final String paramsLog = params.replaceAll(passMatch, "password=***");
Log.i(Settings.tag + " | JSON", "[POST " + (int)(params.length() / 1024) + "k | " + httpCode + " | " + (int)(buffer.length() / 1024) + "k] Downloaded " + "http://" + host + path + "?" + paramsLog);
connection.disconnect();
br.close();
ins.close();
inr.close();
} catch (IOException e) {
Log.e(Settings.tag, "cgeoBase.requestJSONgc.IOException: " + e.toString());
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.requestJSONgc: " + e.toString());
}
if (buffer != null && buffer.length() > 0) {
break;
}
}
String page = null;
if (httpCode == 302 && httpLocation != null) {
final Uri newLocation = Uri.parse(httpLocation);
if (newLocation.isRelative() == true) {
page = requestJSONgc(host, path, params);
} else {
page = requestJSONgc(newLocation.getHost(), newLocation.getPath(), params);
}
} else {
page = replaceWhitespace(buffer);
}
if (page != null) {
return page;
} else {
return "";
}
}
public String requestJSON(String host, String path, String params) {
return requestJSON("http://", host, path, "GET", params);
}
public String requestJSON(String scheme, String host, String path, String method, String params) {
int httpCode = -1;
String httpLocation = null;
if (method == null) {
method = "GET";
} else {
method = method.toUpperCase();
}
boolean methodPost = false;
if (method.equalsIgnoreCase("POST")) {
methodPost = true;
}
URLConnection uc = null;
HttpURLConnection connection = null;
Integer timeout = 30000;
final StringBuffer buffer = new StringBuffer();
for (int i = 0; i < 3; i++) {
if (i > 0) {
Log.w(Settings.tag, "Failed to download data, retrying. Attempt #" + (i + 1));
}
buffer.delete(0, buffer.length());
timeout = 30000 + (i * 15000);
try {
try {
URL u = null;
if (methodPost) {
u = new URL(scheme + host + path);
} else {
u = new URL(scheme + host + path + "?" + params);
}
if (u.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) u.openConnection();
https.setHostnameVerifier(doNotVerify);
uc = https;
} else {
uc = (HttpURLConnection) u.openConnection();
}
uc.setRequestProperty("Host", host);
uc.setRequestProperty("Accept", "application/json, text/javascript, */*; q=0.01");
if (methodPost) {
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
uc.setRequestProperty("Content-Length", Integer.toString(params.length()));
uc.setRequestProperty("X-HTTP-Method-Override", "GET");
} else {
uc.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
}
uc.setRequestProperty("X-Requested-With", "XMLHttpRequest");
connection = (HttpURLConnection) uc;
connection.setReadTimeout(timeout);
connection.setRequestMethod(method);
HttpURLConnection.setFollowRedirects(false); // TODO: Fix these (FilCab)
connection.setDoInput(true);
if (methodPost) {
connection.setDoOutput(true);
final OutputStream out = connection.getOutputStream();
final OutputStreamWriter wr = new OutputStreamWriter(out);
wr.write(params);
wr.flush();
wr.close();
} else {
connection.setDoOutput(false);
}
final String encoding = connection.getContentEncoding();
InputStream ins;
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
ins = new GZIPInputStream(connection.getInputStream());
} else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
ins = new InflaterInputStream(connection.getInputStream(), new Inflater(true));
} else {
ins = connection.getInputStream();
}
final InputStreamReader inr = new InputStreamReader(ins);
final BufferedReader br = new BufferedReader(inr);
readIntoBuffer(br, buffer);
httpCode = connection.getResponseCode();
final String paramsLog = params.replaceAll(passMatch, "password=***");
Log.i(Settings.tag + " | JSON", "[POST " + (int)(params.length() / 1024) + "k | " + httpCode + " | " + (int)(buffer.length() / 1024) + "k] Downloaded " + "http://" + host + path + "?" + paramsLog);
connection.disconnect();
br.close();
ins.close();
inr.close();
} catch (IOException e) {
httpCode = connection.getResponseCode();
Log.e(Settings.tag, "cgeoBase.requestJSON.IOException: " + httpCode + ": " + connection.getResponseMessage() + " ~ " + e.toString());
}
} catch (Exception e) {
Log.e(Settings.tag, "cgeoBase.requestJSON: " + e.toString());
}
if (buffer != null && buffer.length() > 0) {
break;
}
if (httpCode == 403) {
// we're not allowed to download content, so let's move
break;
}
}
String page = null;
if (httpCode == 302 && httpLocation != null) {
final Uri newLocation = Uri.parse(httpLocation);
if (newLocation.isRelative() == true) {
page = requestJSONgc(host, path, params);
} else {
page = requestJSONgc(newLocation.getHost(), newLocation.getPath(), params);
}
} else {
page = replaceWhitespace(buffer);
}
if (page != null) {
return page;
} else {
return "";
}
}
public static String rot13(String text) {
final StringBuilder result = new StringBuilder();
// plaintext flag (do not convert)
boolean plaintext = false;
int length = text.length();
for (int index = 0; index < length; index++) {
int c = text.charAt(index);
if (c == '[') {
plaintext = true;
} else if (c == ']') {
plaintext = false;
} else if (!plaintext) {
int capitalized = c & 32;
c &= ~capitalized;
c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c)
| capitalized;
}
result.append((char) c);
}
return result.toString();
}
public static String md5(String text) {
String hashed = "";
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(text.getBytes(), 0, text.length());
hashed = new BigInteger(1, digest.digest()).toString(16);
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.md5: " + e.toString());
}
return hashed;
}
public static String sha1(String text) {
String hashed = "";
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(text.getBytes(), 0, text.length());
hashed = new BigInteger(1, digest.digest()).toString(16);
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.sha1: " + e.toString());
}
return hashed;
}
public static byte[] hashHmac(String text, String salt) {
byte[] macBytes = {};
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(salt.getBytes(), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKeySpec);
macBytes = mac.doFinal(text.getBytes());
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.hashHmac: " + e.toString());
}
return macBytes;
}
public static boolean deleteDirectory(File path) {
if (path.exists()) {
File[] files = path.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDirectory(files[i]);
} else {
files[i].delete();
}
}
}
return (path.delete());
}
public static boolean isIntentAvailable(Context context, String action) {
final Intent intent = new Intent(action);
return isIntentAvailable(context, intent);
}
public static boolean isIntentAvailable(Context context, Intent intent) {
final PackageManager packageManager = context.getPackageManager();
final List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return (list.size() > 0);
}
public void storeCache(App app, Activity activity, Cache cache, String geocode, int listId, Handler handler) {
try {
// cache details
if (cache != null) {
final HashMap<String, String> params = new HashMap<String, String>();
params.put("geocode", cache.geocode);
final Long searchId = searchByGeocode(params, listId, false);
cache = app.getCache(searchId);
} else if (geocode != null) {
final HashMap<String, String> params = new HashMap<String, String>();
params.put("geocode", geocode);
final Long searchId = searchByGeocode(params, listId, false);
cache = app.getCache(searchId);
}
if (cache == null) {
if (handler != null) {
handler.sendMessage(new Message());
}
return;
}
final HtmlImg imgGetter = new HtmlImg(activity, settings, cache.geocode, false, listId, true);
// store images from description
if (cache.description != null) {
Html.fromHtml(cache.description, imgGetter, null);
}
// store spoilers
if (cache.spoilers != null && cache.spoilers.isEmpty() == false) {
for (Spoiler oneSpoiler : cache.spoilers) {
imgGetter.getDrawable(oneSpoiler.url);
}
}
// store map previews
if (settings.storeOfflineMaps == 1 && cache.latitude != null && cache.longitude != null) {
final String latlonMap = String.format((Locale) null, "%.6f", cache.latitude) + "," + String.format((Locale) null, "%.6f", cache.longitude);
final Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
final int maxWidth = display.getWidth() - 25;
final int maxHeight = display.getHeight() - 25;
int edge = 0;
if (maxWidth > maxHeight) {
edge = maxWidth;
} else {
edge = maxHeight;
}
String type = "mystery";
if (cache.found == true) {
type = cache.type + "_found";
} else if (cache.disabled == true) {
type = cache.type + "_disabled";
} else {
type = cache.type;
}
final String markerUrl = urlencode_rfc3986("http://cgeo.carnero.cc/_markers/marker_cache_" + type + ".png");
final StringBuilder waypoints = new StringBuilder();
if (cache.waypoints != null && cache.waypoints.size() > 0) {
for (Waypoint waypoint : cache.waypoints) {
if (waypoint.latitude == null && waypoint.longitude == null) {
continue;
}
waypoints.append("&markers=icon%3Ahttp://cgeo.carnero.cc/_markers/marker_waypoint_");
waypoints.append(waypoint.type);
waypoints.append(".png%7C");
waypoints.append(String.format((Locale) null, "%.6f", waypoint.latitude));
waypoints.append(",");
waypoints.append(String.format((Locale) null, "%.6f", waypoint.longitude));
}
}
// download map images in separate background thread for higher performance
final String code = cache.geocode;
final int finalEdge = edge;
Thread staticMapsThread = new Thread("getting static map") {@Override
public void run() {
MapImg mapGetter = new MapImg(settings, code);
mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?center=" + latlonMap + "&zoom=20&size=" + finalEdge + "x" + finalEdge + "&maptype=satellite&markers=icon%3A" + markerUrl + "%7C" + latlonMap + waypoints.toString() + "&sensor=false", 1);
mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?center=" + latlonMap + "&zoom=18&size=" + finalEdge + "x" + finalEdge + "&maptype=satellite&markers=icon%3A" + markerUrl + "%7C" + latlonMap + waypoints.toString() + "&sensor=false", 2);
mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?center=" + latlonMap + "&zoom=16&size=" + finalEdge + "x" + finalEdge + "&maptype=roadmap&markers=icon%3A" + markerUrl + "%7C" + latlonMap + waypoints.toString() + "&sensor=false", 3);
mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?center=" + latlonMap + "&zoom=14&size=" + finalEdge + "x" + finalEdge + "&maptype=roadmap&markers=icon%3A" + markerUrl + "%7C" + latlonMap + waypoints.toString() + "&sensor=false", 4);
mapGetter.getDrawable("http://maps.google.com/maps/api/staticmap?center=" + latlonMap + "&zoom=11&size=" + finalEdge + "x" + finalEdge + "&maptype=roadmap&markers=icon%3A" + markerUrl + "%7C" + latlonMap + waypoints.toString() + "&sensor=false", 5);
}};
staticMapsThread.setPriority(Thread.MIN_PRIORITY);
staticMapsThread.start();
}
app.markStored(cache.geocode, listId);
app.removeCacheFromCache(cache.geocode);
if (handler != null) {
handler.sendMessage(new Message());
}
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.storeCache: " + e.toString());
}
}
public void dropCache(App app, Activity activity, Cache cache, Handler handler) {
try {
app.markDropped(cache.geocode);
app.removeCacheFromCache(cache.geocode);
handler.sendMessage(new Message());
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.dropCache: " + e.toString());
}
}
public boolean isInViewPort(int centerLat1, int centerLon1, int centerLat2, int centerLon2, int spanLat1, int spanLon1, int spanLat2, int spanLon2) {
try {
// expects coordinates in E6 format
final int left1 = centerLat1 - (spanLat1 / 2);
final int right1 = centerLat1 + (spanLat1 / 2);
final int top1 = centerLon1 + (spanLon1 / 2);
final int bottom1 = centerLon1 - (spanLon1 / 2);
final int left2 = centerLat2 - (spanLat2 / 2);
final int right2 = centerLat2 + (spanLat2 / 2);
final int top2 = centerLon2 + (spanLon2 / 2);
final int bottom2 = centerLon2 - (spanLon2 / 2);
if (left2 <= left1) {
return false;
}
if (right2 >= right1) {
return false;
}
if (top2 >= top1) {
return false;
}
if (bottom2 <= bottom1) {
return false;
}
return true;
} catch (Exception e) {
Log.e(Settings.tag, "cgBase.isInViewPort: " + e.toString());
return false;
}
}
public boolean isCacheInViewPort(int centerLat, int centerLon, int spanLat, int spanLon, Double cacheLat, Double cacheLon) {
if (cacheLat == null || cacheLon == null) {
return false;
}
// viewport is defined by center, span and some (10%) reserve on every side
int minLat = centerLat - (spanLat / 2) - (spanLat / 10);
int maxLat = centerLat + (spanLat / 2) + (spanLat / 10);
int minLon = centerLon - (spanLon / 2) - (spanLon / 10);
int maxLon = centerLon + (spanLon / 2) + (spanLon / 10);
int cLat = (int) Math.round(cacheLat * 1e6);
int cLon = (int) Math.round(cacheLon * 1e6);
int mid = 0;
if (maxLat < minLat) {
mid = minLat;
minLat = maxLat;
maxLat = mid;
}
if (maxLon < minLon) {
mid = minLon;
minLon = maxLon;
maxLon = mid;
}
boolean latOk = false;
boolean lonOk = false;
if (cLat >= minLat && cLat <= maxLat) {
latOk = true;
}
if (cLon >= minLon && cLon <= maxLon) {
lonOk = true;
}
if (latOk == true && lonOk == true) {
return true;
} else {
return false;
}
}
private static char[] base64map1 = new char[64];
static {
int i = 0;
for (char c = 'A'; c <= 'Z'; c++) {
base64map1[i++] = c;
}
for (char c = 'a'; c <= 'z'; c++) {
base64map1[i++] = c;
}
for (char c = '0'; c <= '9'; c++) {
base64map1[i++] = c;
}
base64map1[i++] = '+';
base64map1[i++] = '/';
}
private static byte[] base64map2 = new byte[128];
static {
for (int i = 0; i < base64map2.length; i++) {
base64map2[i] = -1;
}
for (int i = 0; i < 64; i++) {
base64map2[base64map1[i]] = (byte) i;
}
}
public static String base64Encode(byte[] in) {
int iLen = in.length;
int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
int oLen = ((iLen + 2) / 3) * 4; // output length including padding
char[] out = new char[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
int o0 = i0 >>> 2;
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
int o3 = i2 & 0x3F;
out[op++] = base64map1[o0];
out[op++] = base64map1[o1];
out[op] = op < oDataLen ? base64map1[o2] : '=';
op++;
out[op] = op < oDataLen ? base64map1[o3] : '=';
op++;
}
return new String(out);
}
public static byte[] base64Decode(String text) {
char[] in = text.toCharArray();
int iLen = in.length;
if (iLen % 4 != 0) {
throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4.");
}
while (iLen > 0 && in[iLen - 1] == '=') {
iLen--;
}
int oLen = (iLen * 3) / 4;
byte[] out = new byte[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iLen ? in[ip++] : 'A';
int i3 = ip < iLen ? in[ip++] : 'A';
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) {
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
}
int b0 = base64map2[i0];
int b1 = base64map2[i1];
int b2 = base64map2[i2];
int b3 = base64map2[i3];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) {
throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
}
int o0 = (b0 << 2) | (b1 >>> 4);
int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
int o2 = ((b2 & 3) << 6) | b3;
out[op++] = (byte) o0;
if (op < oLen) {
out[op++] = (byte) o1;
}
if (op < oLen) {
out[op++] = (byte) o2;
}
}
return out;
}
public int getIcon(boolean cache, String type, boolean own, boolean found, boolean disabled) {
if (gcIcons.isEmpty()) {
// default markers
gcIcons.put("ape", R.drawable.marker_cache_ape);
gcIcons.put("cito", R.drawable.marker_cache_cito);
gcIcons.put("earth", R.drawable.marker_cache_earth);
gcIcons.put("event", R.drawable.marker_cache_event);
gcIcons.put("letterbox", R.drawable.marker_cache_letterbox);
gcIcons.put("locationless", R.drawable.marker_cache_locationless);
gcIcons.put("mega", R.drawable.marker_cache_mega);
gcIcons.put("multi", R.drawable.marker_cache_multi);
gcIcons.put("traditional", R.drawable.marker_cache_traditional);
gcIcons.put("virtual", R.drawable.marker_cache_virtual);
gcIcons.put("webcam", R.drawable.marker_cache_webcam);
gcIcons.put("wherigo", R.drawable.marker_cache_wherigo);
gcIcons.put("mystery", R.drawable.marker_cache_mystery);
gcIcons.put("gchq", R.drawable.marker_cache_gchq);
// own cache markers
gcIcons.put("ape-own", R.drawable.marker_cache_ape_own);
gcIcons.put("cito-own", R.drawable.marker_cache_cito_own);
gcIcons.put("earth-own", R.drawable.marker_cache_earth_own);
gcIcons.put("event-own", R.drawable.marker_cache_event_own);
gcIcons.put("letterbox-own", R.drawable.marker_cache_letterbox_own);
gcIcons.put("locationless-own", R.drawable.marker_cache_locationless_own);
gcIcons.put("mega-own", R.drawable.marker_cache_mega_own);
gcIcons.put("multi-own", R.drawable.marker_cache_multi_own);
gcIcons.put("traditional-own", R.drawable.marker_cache_traditional_own);
gcIcons.put("virtual-own", R.drawable.marker_cache_virtual_own);
gcIcons.put("webcam-own", R.drawable.marker_cache_webcam_own);
gcIcons.put("wherigo-own", R.drawable.marker_cache_wherigo_own);
gcIcons.put("mystery-own", R.drawable.marker_cache_mystery_own);
gcIcons.put("gchq-own", R.drawable.marker_cache_gchq_own);
// found cache markers
gcIcons.put("ape-found", R.drawable.marker_cache_ape_found);
gcIcons.put("cito-found", R.drawable.marker_cache_cito_found);
gcIcons.put("earth-found", R.drawable.marker_cache_earth_found);
gcIcons.put("event-found", R.drawable.marker_cache_event_found);
gcIcons.put("letterbox-found", R.drawable.marker_cache_letterbox_found);
gcIcons.put("locationless-found", R.drawable.marker_cache_locationless_found);
gcIcons.put("mega-found", R.drawable.marker_cache_mega_found);
gcIcons.put("multi-found", R.drawable.marker_cache_multi_found);
gcIcons.put("traditional-found", R.drawable.marker_cache_traditional_found);
gcIcons.put("virtual-found", R.drawable.marker_cache_virtual_found);
gcIcons.put("webcam-found", R.drawable.marker_cache_webcam_found);
gcIcons.put("wherigo-found", R.drawable.marker_cache_wherigo_found);
gcIcons.put("mystery-found", R.drawable.marker_cache_mystery_found);
gcIcons.put("gchq-found", R.drawable.marker_cache_gchq_found);
// disabled cache markers
gcIcons.put("ape-disabled", R.drawable.marker_cache_ape_disabled);
gcIcons.put("cito-disabled", R.drawable.marker_cache_cito_disabled);
gcIcons.put("earth-disabled", R.drawable.marker_cache_earth_disabled);
gcIcons.put("event-disabled", R.drawable.marker_cache_event_disabled);
gcIcons.put("letterbox-disabled", R.drawable.marker_cache_letterbox_disabled);
gcIcons.put("locationless-disabled", R.drawable.marker_cache_locationless_disabled);
gcIcons.put("mega-disabled", R.drawable.marker_cache_mega_disabled);
gcIcons.put("multi-disabled", R.drawable.marker_cache_multi_disabled);
gcIcons.put("traditional-disabled", R.drawable.marker_cache_traditional_disabled);
gcIcons.put("virtual-disabled", R.drawable.marker_cache_virtual_disabled);
gcIcons.put("webcam-disabled", R.drawable.marker_cache_webcam_disabled);
gcIcons.put("wherigo-disabled", R.drawable.marker_cache_wherigo_disabled);
gcIcons.put("mystery-disabled", R.drawable.marker_cache_mystery_disabled);
gcIcons.put("gchq-disabled", R.drawable.marker_cache_gchq_disabled);
}
if (wpIcons.isEmpty()) {
wpIcons.put("waypoint", R.drawable.marker_waypoint_waypoint);
wpIcons.put("flag", R.drawable.marker_waypoint_flag);
wpIcons.put("pkg", R.drawable.marker_waypoint_pkg);
wpIcons.put("puzzle", R.drawable.marker_waypoint_puzzle);
wpIcons.put("stage", R.drawable.marker_waypoint_stage);
wpIcons.put("trailhead", R.drawable.marker_waypoint_trailhead);
}
int icon = -1;
String iconTxt = null;
if (cache == true) {
if (type != null && type.length() > 0) {
if (own == true) {
iconTxt = type + "-own";
} else if (found == true) {
iconTxt = type + "-found";
} else if (disabled == true) {
iconTxt = type + "-disabled";
} else {
iconTxt = type;
}
} else {
iconTxt = "traditional";
}
if (gcIcons.containsKey(iconTxt) == true) {
icon = gcIcons.get(iconTxt);
} else {
icon = gcIcons.get("traditional");
}
} else {
if (type != null && type.length() > 0) {
iconTxt = type;
} else {
iconTxt = "waypoint";
}
if (wpIcons.containsKey(iconTxt) == true) {
icon = wpIcons.get(iconTxt);
} else {
icon = wpIcons.get("waypoint");
}
}
return icon;
}
public boolean isLocus(Context context) {
boolean locus = false;
final Intent intentTest = new Intent(Intent.ACTION_VIEW);
intentTest.setData(Uri.parse("menion.points:x"));
if (isIntentAvailable(context, intentTest) == true) {
locus = true;
}
return locus;
}
public boolean isRmaps(Context context) {
boolean rmaps = false;
final Intent intent = new Intent("com.robert.maps.action.SHOW_POINTS");
if (isIntentAvailable(context, intent) == true) {
rmaps = true;
}
return rmaps;
}
public boolean runExternalMap(int application, Activity activity, Resources res, Warning warning, GoogleAnalyticsTracker tracker, Double latitude, Double longitude) {
// waypoint
return runExternalMap(application, activity, res, warning, tracker, null, null, latitude, longitude);
}
public boolean runExternalMap(int application, Activity activity, Resources res, Warning warning, GoogleAnalyticsTracker tracker, Waypoint waypoint) {
// waypoint
return runExternalMap(application, activity, res, warning, tracker, null, waypoint, null, null);
}
public boolean runExternalMap(int application, Activity activity, Resources res, Warning warning, GoogleAnalyticsTracker tracker, Cache cache) {
// cache
return runExternalMap(application, activity, res, warning, tracker, cache, null, null, null);
}
public boolean runExternalMap(int application, Activity activity, Resources res, Warning warning, GoogleAnalyticsTracker tracker, Cache cache, Waypoint waypoint, Double latitude, Double longitude) {
if (cache == null && waypoint == null && latitude == null && longitude == null) {
return false;
}
if (application == mapAppLocus) {
// locus
try {
final Intent intentTest = new Intent(Intent.ACTION_VIEW);
intentTest.setData(Uri.parse("menion.points:x"));
if (isIntentAvailable(activity, intentTest) == true) {
final ArrayList<Waypoint> waypoints = new ArrayList<Waypoint>();
// get only waypoints with coordinates
if (cache != null && cache.waypoints != null && cache.waypoints.isEmpty() == false) {
for (Waypoint wp : cache.waypoints) {
if (wp.latitude != null && wp.longitude != null) {
waypoints.add(wp);
}
}
}
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(1); // not used
if (cache != null) {
if (waypoints == null || waypoints.isEmpty() == true) {
dos.writeInt(1); // cache only
} else {
dos.writeInt((1 + waypoints.size())); // cache and waypoints
}
} else {
dos.writeInt(1); // one waypoint
}
int icon = -1;
if (cache != null) {
icon = getIcon(true, cache.type, cache.own, cache.found, cache.disabled || cache.archived);
} else if (waypoint != null) {
icon = getIcon(false, waypoint.type, false, false, false);
} else {
icon = getIcon(false, "waypoint", false, false, false);
}
if (icon > 0) {
// load icon
Bitmap bitmap = BitmapFactory.decodeResource(res, icon);
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos2);
byte[] image = baos2.toByteArray();
dos.writeInt(image.length);
dos.write(image);
} else {
// no icon
dos.writeInt(0); // no image
}
// name
if (cache != null && cache.name != null && cache.name.length() > 0) {
dos.writeUTF(cache.name);
} else if (waypoint != null && waypoint.name != null && waypoint.name.length() > 0) {
dos.writeUTF(waypoint.name);
} else {
dos.writeUTF("");
}
// description
if (cache != null && cache.geocode != null && cache.geocode.length() > 0) {
dos.writeUTF(cache.geocode.toUpperCase());
} else if (waypoint != null && waypoint.lookup != null && waypoint.lookup.length() > 0) {
dos.writeUTF(waypoint.lookup.toUpperCase());
} else {
dos.writeUTF("");
}
// additional data :: keyword, button title, package, activity, data name, data content
if (cache != null && cache.geocode != null && cache.geocode.length() > 0) {
dos.writeUTF("intent;c:geo;carnero.cgeo;carnero.cgeo.cgeodetail;geocode;" + cache.geocode);
} else if (waypoint != null && waypoint.id != null && waypoint.id > 0) {
dos.writeUTF("intent;c:geo;carnero.cgeo;carnero.cgeo.cgeowaypoint;id;" + waypoint.id);
} else {
dos.writeUTF("");
}
if (cache != null && cache.latitude != null && cache.longitude != null) {
dos.writeDouble(cache.latitude); // latitude
dos.writeDouble(cache.longitude); // longitude
} else if (waypoint != null && waypoint.latitude != null && waypoint.longitude != null) {
dos.writeDouble(waypoint.latitude); // latitude
dos.writeDouble(waypoint.longitude); // longitude
} else {
dos.writeDouble(latitude); // latitude
dos.writeDouble(longitude); // longitude
}
// cache waypoints
if (waypoints != null && waypoints.isEmpty() == false) {
for (Waypoint wp : waypoints) {
if (wp == null || wp.latitude == null || wp.longitude == null) {
continue;
}
final int wpIcon = getIcon(false, wp.type, false, false, false);
if (wpIcon > 0) {
// load icon
Bitmap bitmap = BitmapFactory.decodeResource(res, wpIcon);
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos2);
byte[] image = baos2.toByteArray();
dos.writeInt(image.length);
dos.write(image);
} else {
// no icon
dos.writeInt(0); // no image
}
// name
if (wp.lookup != null && wp.lookup.length() > 0) {
dos.writeUTF(wp.lookup.toUpperCase());
} else {
dos.writeUTF("");
}
// description
if (wp.name != null && wp.name.length() > 0) {
dos.writeUTF(wp.name);
} else {
dos.writeUTF("");
}
// additional data :: keyword, button title, package, activity, data name, data content
if (wp.id != null && wp.id > 0) {
dos.writeUTF("intent;c:geo;carnero.cgeo;carnero.cgeo.cgeowaypoint;id;" + wp.id);
} else {
dos.writeUTF("");
}
dos.writeDouble(wp.latitude); // latitude
dos.writeDouble(wp.longitude); // longitude
}
}
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("menion.points:data"));
intent.putExtra("data", baos.toByteArray());
activity.startActivity(intent);
sendAnal(activity, tracker, "/external/locus");
return true;
}
} catch (Exception e) {
// nothing
}
}
if (application == mapAppRmaps) {
// rmaps
try {
final Intent intent = new Intent("com.robert.maps.action.SHOW_POINTS");
if (isIntentAvailable(activity, intent) == true) {
final ArrayList<String> locations = new ArrayList<String>();
if (cache != null && cache.latitude != null && cache.longitude != null) {
locations.add(String.format((Locale) null, "%.6f", cache.latitude) + "," + String.format((Locale) null, "%.6f", cache.longitude) + ";" + cache.geocode + ";" + cache.name);
} else if (waypoint != null && waypoint.latitude != null && waypoint.longitude != null) {
locations.add(String.format((Locale) null, "%.6f", waypoint.latitude) + "," + String.format((Locale) null, "%.6f", waypoint.longitude) + ";" + waypoint.lookup + ";" + waypoint.name);
}
intent.putStringArrayListExtra("locations", locations);
activity.startActivity(intent);
sendAnal(activity, tracker, "/external/rmaps");
return true;
}
} catch (Exception e) {
// nothing
}
}
if (application == mapAppAny) {
// fallback
try {
if (cache != null && cache.latitude != null && cache.longitude != null) {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("geo:" + cache.latitude + "," + cache.longitude)));
// INFO: q parameter works with Google Maps, but breaks cooperation with all other apps
} else if (waypoint != null && waypoint.latitude != null && waypoint.longitude != null) {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("geo:" + waypoint.latitude + "," + waypoint.longitude)));
// INFO: q parameter works with Google Maps, but breaks cooperation with all other apps
}
sendAnal(activity, tracker, "/external/native/maps");
return true;
} catch (Exception e) {
// nothing
}
}
Log.i(Settings.tag, "cgBase.runExternalMap: No maps application available.");
if (warning != null && res != null) {
warning.showToast(res.getString(R.string.err_application_no));
}
return false;
}
public boolean runNavigation(Activity activity, Resources res, Settings settings, Warning warning, GoogleAnalyticsTracker tracker, Double latitude, Double longitude) {
return runNavigation(activity, res, settings, warning, tracker, latitude, longitude, null, null);
}
public boolean runNavigation(Activity activity, Resources res, Settings settings, Warning warning, GoogleAnalyticsTracker tracker, Double latitude, Double longitude, Double latitudeNow, Double longitudeNow) {
if (activity == null) {
return false;
}
if (settings == null) {
return false;
}
// Google Navigation
if (settings.useGNavigation == 1) {
try {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:ll=" + latitude + "," + longitude)));
sendAnal(activity, tracker, "/external/native/navigation");
return true;
} catch (Exception e) {
// nothing
}
}
// Google Maps Directions
try {
if (latitudeNow != null && longitudeNow != null) {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?f=d&saddr=" + latitudeNow + "," + longitudeNow + "&daddr=" + latitude + "," + longitude)));
} else {
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?f=d&daddr=" + latitude + "," + longitude)));
}
sendAnal(activity, tracker, "/external/native/maps");
return true;
} catch (Exception e) {
// nothing
}
Log.i(Settings.tag, "cgBase.runNavigation: No navigation application available.");
if (warning != null && res != null) {
warning.showToast(res.getString(R.string.err_navigation_no));
}
return false;
}
public String getMapUserToken(Handler noTokenHandler) {
final Response response = request(false, "www.geocaching.com", "/map/default.aspx", "GET", "", 0, false);
final String data = response.getData();
String usertoken = null;
if (data != null && data.length() > 0) {
final Pattern pattern = Pattern.compile("var userToken[^=]*=[^']*'([^']+)';", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(data);
while (matcher.find()) {
if (matcher.groupCount() > 0) {
usertoken = matcher.group(1);
}
}
}
if (noTokenHandler != null && (usertoken == null || usertoken.length() == 0)) {
noTokenHandler.sendEmptyMessage(0);
}
return usertoken;
}
public void sendAnal(Context context, String page) {
(new sendAnalThread(context, null, page)).start();
}
public void sendAnal(Context context, GoogleAnalyticsTracker tracker, String page) {
(new sendAnalThread(context, tracker, page)).start();
}
private class sendAnalThread extends Thread {
Context context = null;
GoogleAnalyticsTracker tracker = null;
String page = null;
boolean startedHere = false;
public sendAnalThread(Context contextIn, GoogleAnalyticsTracker trackerIn, String pageIn) {
context = contextIn;
tracker = trackerIn;
page = pageIn;
}
@Override
public void run() {
try {
if (page == null || page.length() == 0) {
page = "/";
}
if (tracker == null && context != null) {
startedHere = true;
tracker = GoogleAnalyticsTracker.getInstance();
tracker.start(Settings.analytics, context);
}
tracker.trackPageView(page);
tracker.dispatch();
Log.i(Settings.tag, "Logged use of " + page);
if (startedHere == true) {
tracker.stop();
}
} catch (Exception e) {
// nothing
}
}
}
public Double getElevation(Double latitude, Double longitude) {
Double elv = null;
try {
final String host = "maps.googleapis.com";
final String path = "/maps/api/elevation/json";
final String params = "sensor=false&locations=" + String.format((Locale) null, "%.6f", latitude) + "," + String.format((Locale) null, "%.6f", longitude);
final String data = requestJSON(host, path, params);
if (data == null || data.length() == 0) {
return elv;
}
JSONObject response = new JSONObject(data);
String status = response.getString("status");
if (status == null || status.equalsIgnoreCase("OK") == false) {
return elv;
}
if (response.has("results") == true) {
JSONArray results = response.getJSONArray("results");
JSONObject result = results.getJSONObject(0);
elv = result.getDouble("elevation");
}
} catch (Exception e) {
Log.w(Settings.tag, "cgBase.getElevation: " + e.toString());
}
return elv;
}
public void showProgress(Activity activity, boolean status) {
if (activity == null) {
return;
}
final ProgressBar progress = (ProgressBar) activity.findViewById(R.id.actionbar_progress);
if (status == true) {
progress.setVisibility(View.VISIBLE);
} else {
progress.setVisibility(View.GONE);
}
}
public void goHome(Activity activity) {
final Intent intent = new Intent(activity, main.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(intent);
activity.finish();
}
public void setTitle(Activity activity, String text) {
if (activity == null || text == null) {
return;
}
final TextView title = (TextView) activity.findViewById(R.id.actionbar_title);
if (title != null) {
title.setText(text);
}
}
}