Example usage for android.text.style StrikethroughSpan StrikethroughSpan

List of usage examples for android.text.style StrikethroughSpan StrikethroughSpan

Introduction

In this page you can find the example usage for android.text.style StrikethroughSpan StrikethroughSpan.

Prototype

public StrikethroughSpan() 

Source Link

Document

Creates a StrikethroughSpan .

Usage

From source file:org.miaowo.miaowo.util.Html.java

private static void endCssStyle(Editable text) {
    Strikethrough s = getLast(text, Strikethrough.class);
    if (s != null) {
        setSpanFromMark(text, s, new StrikethroughSpan());
    }//from  w  w w  . j a va  2 s . c o  m

    Background b = getLast(text, Background.class);
    if (b != null) {
        setSpanFromMark(text, b, new BackgroundColorSpan(b.mBackgroundColor));
    }

    Foreground f = getLast(text, Foreground.class);
    if (f != null) {
        setSpanFromMark(text, f, new ForegroundColorSpan(f.mForegroundColor));
    }
}

From source file:carnero.cgeo.cgBase.java

public cgCacheWrap parseSearch(cgSearchThread thread, String url, String page, boolean showCaptcha) {
    if (page == null || page.length() == 0) {
        Log.e(cgSettings.tag, "cgeoBase.parseSearch: No page given");
        return null;
    }//from  w ww  .j a  v a  2 s.  c  o  m

    final cgCacheWrap caches = new cgCacheWrap();
    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(cgSettings.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(cgSettings.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(cgSettings.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++) {
        cgCache cache = new cgCache();
        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(cgSettings.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(cgSettings.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(cgSettings.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(cgSettings.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(cgSettings.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(cgSettings.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.gif") != -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(cgSettings.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(cgSettings.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(cgSettings.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(cgSettings.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(cgSettings.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, cgCoord> cidCoords = new HashMap<String, cgCoord>();
                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 cgCoord pointCoord = new cgCoord();
                    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(cgSettings.tag, "Coordinates found in .loc file: " + cidCoords.size());

                // save found cache coordinates
                for (cgCache oneCache : caches.cacheList) {
                    if (cidCoords.containsKey(oneCache.geocode) == true) {
                        cgCoord 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(cgSettings.tag, "cgBase.parseSearch.CIDs: " + e.toString());
        }
    }

    // get direction images
    cgDirectionImg dirImgDownloader = new cgDirectionImg(settings);
    for (cgCache oneCache : caches.cacheList) {
        if (oneCache.latitude == null && oneCache.longitude == null && oneCache.direction == null
                && oneCache.directionImg != null) {
            dirImgDownloader.getDrawable(oneCache.geocode, oneCache.directionImg);
        }
    }
    dirImgDownloader = null;

    // get ratings
    if (guids.size() > 0) {
        Log.i(cgSettings.tag, "Trying to get ratings for " + cids.size() + " caches");

        try {
            final HashMap<String, cgRating> ratings = getRating(guids, null);

            if (ratings != null) {
                // save found cache coordinates
                for (cgCache oneCache : caches.cacheList) {
                    if (ratings.containsKey(oneCache.guid) == true) {
                        cgRating thisRating = ratings.get(oneCache.guid);

                        oneCache.rating = thisRating.rating;
                        oneCache.votes = thisRating.votes;
                        oneCache.myVote = thisRating.myVote;
                    }
                }
            }
        } catch (Exception e) {
            Log.e(cgSettings.tag, "cgBase.parseSearch.GCvote: " + e.toString());
        }
    }

    return caches;
}

From source file:carnero.cgeo.original.libs.Base.java

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;
    }//from   w  w w  . j  a va  2  s . c  om

    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;
}

From source file:cgeo.geocaching.cgBase.java

public cgCacheWrap parseSearch(cgSearchThread thread, String url, String page, boolean showCaptcha) {
    if (StringUtils.isBlank(page)) {
        Log.e(cgSettings.tag, "cgeoBase.parseSearch: No page given");
        return null;
    }//  w  w w. j a  va  2s . c om

    final cgCacheWrap caches = new cgCacheWrap();
    final List<String> cids = new ArrayList<String>();
    final List<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.viewstates = getViewstates(page);

    // recaptcha
    if (showCaptcha) {
        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 (StringUtils.isNotBlank(recaptchaJs)) {
                    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(cgSettings.tag, "cgeoBase.parseSearch: Failed to parse recaptcha challenge");
        }

        if (thread != null && StringUtils.isNotBlank(recaptchaChallenge)) {
            thread.setChallenge(recaptchaChallenge);
            thread.notifyNeed();
        }
    }

    if (!page.contains("SearchResultsTable")) {
        // there are no results. aborting here avoids a wrong error log in the next parsing step
        return caches;
    }

    int startPos = page.indexOf("<div id=\"ctl00_ContentBody_ResultsPanel\"");
    if (startPos == -1) {
        Log.e(cgSettings.tag, "cgeoBase.parseSearch: ID \"ctl00_ContentBody_dlResults\" not found on page");
        return null;
    }

    page = page.substring(startPos); // cut on <table

    startPos = page.indexOf(">");
    int endPos = page.indexOf("ctl00_ContentBody_UnitTxt");
    if (startPos == -1 || endPos == -1) {
        Log.e(cgSettings.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++) {
        cgCache cache = new cgCache();
        String row = rows[z];

        // check for cache type presence
        if (!row.contains("images/wpttypes")) {
            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")) {
                            cache.disabled = true;
                        } else {
                            cache.disabled = false;
                        }

                        if (attr.contains("OldWarning")) {
                            cache.archived = true;
                        } else {
                            cache.archived = false;
                        }
                    }
                }
            }
        } catch (Exception e) {
            // failed to parse GUID and/or Disabled
            Log.w(cgSettings.tag, "cgeoBase.parseSearch: Failed to parse GUID and/or Disabled data");
        }

        if (settings.excludeDisabled == 1 && (cache.disabled || cache.archived)) {
            // 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(cgSettings.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(cgSettings.tag, "cgeoBase.parseSearch: Failed to parse cache type");
        }

        // cache direction - image
        if (settings.getLoadDirImg()) {
            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(cgSettings.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(cgSettings.tag, "cgeoBase.parseSearch: Failed to parse cache inventory (1)");
        }

        if (StringUtils.isNotBlank(inventoryPre)) {
            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(cgSettings.tag, "cgeoBase.parseSearch: Failed to parse cache inventory info");
            }
        }

        // premium cache
        cache.members = row.contains("/images/small_profile.gif");

        // found it
        cache.found = row.contains("/images/icons/icon_smile");

        // own it
        cache.own = row.contains("/images/silk/star.png");

        // 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(cgSettings.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(cgSettings.tag, "cgeoBase.parseSearch: Failed to parse favourite count");
        }

        if (cache.nameSp == null) {
            cache.nameSp = (new Spannable.Factory()).newSpannable(cache.name);
            if (cache.disabled || cache.archived) { // 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 = Integer.valueOf(matcherTotalCnt.group(1));
                }
            }
        }
    } catch (Exception e) {
        // failed to parse cache count
        Log.w(cgSettings.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 && StringUtils.isNotBlank(recaptchaText)))) {
        Log.i(cgSettings.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=&__EVENTARGUMENT=");
            if (ArrayUtils.isNotEmpty(caches.viewstates)) {
                params.append("&__VIEWSTATE=");
                params.append(urlencode_rfc3986(caches.viewstates[0]));
                if (caches.viewstates.length > 1) {
                    for (int i = 1; i < caches.viewstates.length; i++) {
                        params.append("&__VIEWSTATE" + i + "=");
                        params.append(urlencode_rfc3986(caches.viewstates[i]));
                    }
                    params.append("&__VIEWSTATEFIELDCOUNT=" + caches.viewstates.length);
                }
            }
            for (String cid : cids) {
                params.append("&CID=");
                params.append(urlencode_rfc3986(cid));
            }

            if (recaptchaChallenge != null && StringUtils.isNotBlank(recaptchaText)) {
                params.append("&recaptcha_challenge_field=");
                params.append(urlencode_rfc3986(recaptchaChallenge));
                params.append("&recaptcha_response_field=");
                params.append(urlencode_rfc3986(recaptchaText));
            }
            params.append("&ctl00%24ContentBody%24uxDownloadLoc=Download+Waypoints");

            final String coordinates = request(false, host, path, "POST", params.toString(), 0, true).getData();

            if (StringUtils.isNotBlank(coordinates)) {
                if (coordinates.contains(
                        "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")) {
                    Log.i(cgSettings.tag,
                            "User has not agreed to the license agreement. Can\'t download .loc file.");

                    caches.error = errorRetrieve.get(-7);

                    return caches;
                }
            }

            LocParser.parseLoc(caches, coordinates);
        } catch (Exception e) {
            Log.e(cgSettings.tag, "cgBase.parseSearch.CIDs: " + e.toString());
        }
    }

    // get direction images
    if (settings.getLoadDirImg()) {
        for (cgCache oneCache : caches.cacheList) {
            if (oneCache.coords == null && oneCache.directionImg != null) {
                cgDirectionImg.getDrawable(oneCache.geocode, oneCache.directionImg);
            }
        }
    }

    // get ratings
    if (guids.size() > 0) {
        Log.i(cgSettings.tag, "Trying to get ratings for " + cids.size() + " caches");

        try {
            final Map<String, cgRating> ratings = getRating(guids, null);

            if (CollectionUtils.isNotEmpty(ratings)) {
                // save found cache coordinates
                for (cgCache oneCache : caches.cacheList) {
                    if (ratings.containsKey(oneCache.guid)) {
                        cgRating thisRating = ratings.get(oneCache.guid);

                        oneCache.rating = thisRating.rating;
                        oneCache.votes = thisRating.votes;
                        oneCache.myVote = thisRating.myVote;
                    }
                }
            }
        } catch (Exception e) {
            Log.e(cgSettings.tag, "cgBase.parseSearch.GCvote: " + e.toString());
        }
    }

    return caches;
}