package cgeo.geocaching.connector.gc; import java.util.Locale; import java.util.regex.Pattern; /** * These patterns have been optimized for speed. Improve them only if you can prove * that *YOUR* pattern is faster. Use RegExRealPerformanceTest to show. * * For further information about patterns have a look at * http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html */ public final class GCConstants { static final String GC_URL = "http://www.geocaching.com/"; /** Live Map */ public final static String URL_LIVE_MAP = GC_URL + "map/default.aspx"; /** Live Map pop-up */ public final static String URL_LIVE_MAP_DETAILS = GC_URL + "map/map.details"; /** Caches in a tile */ public final static String URL_MAP_INFO = GC_URL + "map/map.info"; /** Tile itself */ public final static String URL_MAP_TILE = GC_URL + "map/map.png"; /** * Patterns for parsing the result of a (detailed) search */ public final static Pattern PATTERN_HINT = Pattern.compile("
]*>(.*?)
"); public final static Pattern PATTERN_DESC = Pattern.compile("(.*?)\\s*\\s*

\\s*

\\s*

"); public final static Pattern PATTERN_SHORTDESC = Pattern.compile("(.*?)\\s*"); public final static Pattern PATTERN_GEOCODE = Pattern.compile("class=\"CoordInfoCode\">(GC[0-9A-Z]+)"); public final static Pattern PATTERN_CACHEID = Pattern.compile("/seek/log\\.aspx\\?ID=(\\d+)"); public final static Pattern PATTERN_GUID = Pattern.compile(Pattern.quote("&wid=") + "([0-9a-z\\-]+)" + Pattern.quote("&")); public final static Pattern PATTERN_SIZE = Pattern.compile("

[^<]*]*>[^S]*Size[^:]*:[^<]*]*>[^<]*\"\\w+:]*>[^<]*[^<]*[^<]*[^<]*

"); public final static Pattern PATTERN_LATLON = Pattern.compile("]*>(.*?)"); public final static Pattern PATTERN_LATLON_ORIG = Pattern.compile("\\{\"isUserDefined\":true[^}]+?\"oldLatLngDisplay\":\"([^\"]+)\"\\}"); public final static Pattern PATTERN_LOCATION = Pattern.compile(Pattern.quote("In ") + "(?:]*>)?(.*?)<"); public final static Pattern PATTERN_PERSONALNOTE = Pattern.compile("

]*>(.*?)

"); public final static Pattern PATTERN_NAME = Pattern.compile("(.*?)"); public final static Pattern PATTERN_DIFFICULTY = Pattern.compile("]*>[^<]*]*>[^<]*]*>[^<]*
[^<]*

"); public final static Pattern PATTERN_FOUND_ALTERNATIVE = Pattern.compile("
[^<]*

"); public final static Pattern PATTERN_OWNER_DISPLAYNAME = Pattern.compile("
[^<]+([^<]+)
"); public final static Pattern PATTERN_TYPE = Pattern.compile("\"([^\"]+?)\"[^]*>"); public final static Pattern PATTERN_HIDDEN = Pattern.compile("
\\W*Hidden[\\s:]*([^<]+?)
"); public final static Pattern PATTERN_HIDDENEVENT = Pattern.compile("Event\\s*Date\\s*:\\s*([^<]+)
", Pattern.DOTALL); public final static Pattern PATTERN_FAVORITE = Pattern.compile("
"); // without 'class="hideMe"' inside the tag ! public final static Pattern PATTERN_FAVORITECOUNT = Pattern.compile("]+>[^<]*\\D*([0-9]+?)"); public final static Pattern PATTERN_COUNTLOGS = Pattern.compile(""); public final static Pattern PATTERN_LOGBOOK = Pattern.compile("initalLogs = (\\{.+\\});"); // The "inital" typo really comes from gc.com site /** Two groups ! */ public final static Pattern PATTERN_COUNTLOG = Pattern.compile("]+> (\\d*[,.]?\\d+)"); public static final Pattern PATTERN_PREMIUMMEMBERS = Pattern.compile("

This is a Premium Member Only cache.

"); public final static Pattern PATTERN_ATTRIBUTES = Pattern.compile("

.+?Attributes

[^<]*
((?:[^<]*\"[^\"]+\"[^]*>)+?)[^<]*]+>]+>([^<]+)(?:
([^<]+)

)?"); public final static Pattern PATTERN_INVENTORY = Pattern.compile("\\W*Inventory[^<]*[^<]*[^<]*
([^<]*
    (([^<]*
  • [^<]*]*>[^<]*]*>[^<]*[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?"); public final static Pattern PATTERN_INVENTORYINSIDE = Pattern.compile("[^<]*
  • [^<]*]*>[^<]*]*>[^<]*([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>"); public final static Pattern PATTERN_WATCHLIST = Pattern.compile("icon_stop_watchlist.gif"); // Info box top-right public static final Pattern PATTERN_LOGIN_NAME = Pattern.compile("\"SignedInProfileLink\">([^<]+)"); public static final Pattern PATTERN_MEMBER_STATUS = Pattern.compile("([^<]+)"); public static final String MEMBER_STATUS_RENEW = ".*?([\\d,.]+) Caches Found"); public static final Pattern PATTERN_AVATAR_IMAGE_PROFILE_PAGE = Pattern.compile("]*\\salt=\"Avatar\""); public static final Pattern PATTERN_LOGIN_NAME_LOGIN_PAGE = Pattern.compile("

    Success:

    You are logged in as[^<]*]*>([^<]+)[^<]*"); public static final Pattern PATTERN_CUSTOMDATE = Pattern.compile("]*>[^<]*"); public final static Pattern PATTERN_TRACKABLE_GEOCODE = Pattern.compile("(TB[0-9A-Z]+)[^<]* to reference this item."); // multiple error codes, depending on the search term for the trackable code public final static String ERROR_TB_DOES_NOT_EXIST = "does not exist in the system"; public final static String ERROR_TB_ELEMENT_EXCEPTION = "ElementNotFound Exception"; public final static String ERROR_TB_ARITHMETIC_OVERFLOW = "operation resulted in an overflow"; /** * some parts of the webpage don't correctly encode the name, therefore this pattern must be checked with a * trackable name that needs HTML encoding */ public final static Pattern PATTERN_TRACKABLE_NAME = Pattern.compile("name=\"og:title\" content=\"([^\"]+)\""); /** Two groups ! */ public final static Pattern PATTERN_TRACKABLE_OWNER = Pattern.compile("

    \\W*Owner:[^<]*
    [^<]*
    [^<]*([^<]+)<\\/a>[^<]*
    "); public final static Pattern PATTERN_TRACKABLE_RELEASES = Pattern.compile("
    \\W*Released:[^<]*
    [^<]*
    [^<]*([^<]+)<\\/span>[^<]*
    "); public final static Pattern PATTERN_TRACKABLE_ORIGIN = Pattern.compile("
    \\W*Origin:[^<]*
    [^<]*
    [^<]*([^<]+)<\\/span>[^<]*
    "); /** Two groups ! */ public final static Pattern PATTERN_TRACKABLE_SPOTTEDCACHE = Pattern.compile("
    \\W*Recently Spotted:[^<]*
    [^<]*
    [^<]*In ([^<]+)[^<]*
    "); /** Two groups ! */ public final static Pattern PATTERN_TRACKABLE_SPOTTEDUSER = Pattern.compile("
    \\W*Recently Spotted:[^<]*
    [^<]*
    [^<]*In the hands of ([^<]+).[^<]*
    "); public final static Pattern PATTERN_TRACKABLE_SPOTTEDUNKNOWN = Pattern.compile("
    \\W*Recently Spotted:[^<]*
    [^<]*
    [^<]*Unknown Location[^<]*[^<]*
    "); public final static Pattern PATTERN_TRACKABLE_SPOTTEDOWNER = Pattern.compile("
    \\W*Recently Spotted:[^<]*
    [^<]*
    [^<]*In the hands of the owner[^<]*[^<]*
    "); public final static Pattern PATTERN_TRACKABLE_GOAL = Pattern.compile("
    [^<]*

    (.*?)

    [^<]*
    ", Pattern.DOTALL); /** Four groups */ public final static Pattern PATTERN_TRACKABLE_DETAILSIMAGE = Pattern.compile("

    \\W*About This Item[^<]*

    [^<]*
    ([^<]*

    ([^<]*]*>)?[^<]*

    )?[^<]*]*>(.*)

    [^<]*
    "); public final static Pattern PATTERN_TRACKABLE_ICON = Pattern.compile("]*>"); public final static Pattern PATTERN_TRACKABLE_TYPE = Pattern.compile("\"([^\"]+)\"[^]*>"); public final static Pattern PATTERN_TRACKABLE_DISTANCE = Pattern.compile("]*\\W*Tracking History \\(([0-9.,]+(km|mi))[^\\)]*\\)"); public final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("]+> ([^<]+).+?guid.+?>([^<]+).+?(?:guid=([^\"]+)\">(]+>)?([^<]+)\\s*
    (.*?)
    \\s*(?:)?\\s*\\s*"); public final static Pattern PATTERN_TRACKABLE_LOG_IMAGES = Pattern.compile("
  • ([^<]+)[^<]*]+>[^<]*\"([^\"]+)\"]*>[^<]*"); public final static Pattern PATTERN_SEARCH_GUIDANDDISABLED = Pattern.compile("]*>[^<]*[^<]*([^<]*)?([^<]*)([^<]*)?[^<]+
    ([^<]*)]+>([^<]*)([^<]*]+>)?[^<]*
    [^<]*"); /** Two groups **/ public final static Pattern PATTERN_SEARCH_TRACKABLES = Pattern.compile("]*>(.*)"); /** Second group used */ public final static Pattern PATTERN_SEARCH_TRACKABLESINSIDE = Pattern.compile("(\"([^\"]+)\"[^<]*)"); public final static Pattern PATTERN_SEARCH_DIRECTION = Pattern.compile("]*>"); public final static Pattern PATTERN_SEARCH_GEOCODE = Pattern.compile("\\|\\W*(GC[0-9A-Z]+)[^\\|]*\\|"); public final static Pattern PATTERN_SEARCH_ID = Pattern.compile("name=\"CID\"[^v]*value=\"([0-9]+)\""); public final static Pattern PATTERN_SEARCH_FAVORITE = Pattern.compile("([0-9]+)"); public final static Pattern PATTERN_SEARCH_TOTALCOUNT = Pattern.compile("Total Records[^<]*(\\d+)<\\/b>"); public final static Pattern PATTERN_SEARCH_RECAPTCHA = Pattern.compile("]*src=\"[^\"]*/recaptcha/api/challenge\\?k=([^\"]+)\"[^>]*>"); public final static Pattern PATTERN_SEARCH_RECAPTCHACHALLENGE = Pattern.compile("challenge : '([^']+)'"); /** * Patterns for waypoints */ public final static Pattern PATTERN_WPTYPE = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg"); public final static Pattern PATTERN_WPPREFIXORLOOKUPORLATLON = Pattern.compile(">([^<]*<[^>]+>)?([^<]+)(<[^>]+>[^<]*)?<\\/td>"); public final static Pattern PATTERN_WPNAME = Pattern.compile(">[^<]*]+>([^<]*)<\\/a>"); public final static Pattern PATTERN_WPNOTE = Pattern.compile("colspan=\"6\">(.*)<\\/td>"); /** * Patterns for different purposes */ /** replace linebreak and paragraph tags */ public final static Pattern PATTERN_LINEBREAK = Pattern.compile("<(br|p)[^>]*>"); public final static Pattern PATTERN_TYPEBOX = Pattern.compile("", Pattern.CASE_INSENSITIVE); public final static Pattern PATTERN_TYPE2 = Pattern.compile("[^<]+", Pattern.CASE_INSENSITIVE); // FIXME: pattern is over specified public final static Pattern PATTERN_TRACKABLE = Pattern.compile("]*>" + "[^<]*[^<]*([A-Z0-9]+)[^<]*[^<]*([^<]+)[^<]*" + "[^<]*[^<]*[^<]*", Pattern.CASE_INSENSITIVE); public final static Pattern PATTERN_MAINTENANCE = Pattern.compile("]*>([^<]*]*>)?([^<]+)([^<]*)?", Pattern.CASE_INSENSITIVE); public final static Pattern PATTERN_OK1 = Pattern.compile("]*>[^<]*]*>[^<]*[^<]*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_OK2 = Pattern.compile("
    ", Pattern.CASE_INSENSITIVE); public final static Pattern PATTERN_VIEWSTATEFIELDCOUNT = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'"); /** * Patterns for GC and TB codes */ public final static Pattern PATTERN_GC_CODE = Pattern.compile("GC[0-9A-Z]+", Pattern.CASE_INSENSITIVE); public final static Pattern PATTERN_TB_CODE = Pattern.compile("TB[0-9A-Z]+", Pattern.CASE_INSENSITIVE); /** Live Map since 14.02.2012 */ public final static Pattern PATTERN_USERSESSION = Pattern.compile("UserSession\\('([^']+)'"); public final static Pattern PATTERN_SESSIONTOKEN = Pattern.compile("sessionToken:'([^']+)'"); public final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only."; public final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only."; public final static String STRING_UNPUBLISHED_OWNER = "Cache is Unpublished"; public final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published"; public final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred"; public final static String STRING_DISABLED = "
  • This cache is temporarily unavailable."; public final static String STRING_ARCHIVED = "
  • This cache has been archived,"; public final static String STRING_CACHEDETAILS = "id=\"cacheDetails\""; /** Number of logs to retrieve from GC.com */ public final static int NUMBER_OF_LOGS = 35; private final static String SEQUENCE_GCID = "0123456789ABCDEFGHJKMNPQRTVWXYZ"; private final static long GC_BASE31 = 31; private final static long GC_BASE16 = 16; /** * Convert GCCode (geocode) to (old) GCIds * * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 * see http://support.groundspeak.com/index.php?pg=kb.printer.friendly&id=1#p221 */ public static long gccodeToGCId(final String gccode) { long gcid = 0; long base = GC_BASE31; String geocodeWO = gccode.substring(2).toUpperCase(Locale.US); if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) { base = GC_BASE16; } for (int p = 0; p < geocodeWO.length(); p++) { gcid = base * gcid + SEQUENCE_GCID.indexOf(geocodeWO.charAt(p)); } if (base == GC_BASE31) { gcid += Math.pow(16, 4) - 16 * Math.pow(31, 3); } return gcid; } private GCConstants() { // this class shall not have instances } }