Example usage for java.util.regex Pattern DOTALL

List of usage examples for java.util.regex Pattern DOTALL

Introduction

In this page you can find the example usage for java.util.regex Pattern DOTALL.

Prototype

int DOTALL

To view the source code for java.util.regex Pattern DOTALL.

Click Source Link

Document

Enables dotall mode.

Usage

From source file:com.vmware.identity.samlservice.SamlServiceTest.java

@Test
public void testBuildPostResponseForm() throws UnmarshallingException {
    Response response = service.createSamlResponse("42", acsUrl, OasisNames.REQUESTER,
            OasisNames.REQUEST_UNSUPPORTED, RESPONSE_MESSAGE, null);
    String relayState = "{\"dest\":\"d2d25106-44ee-4e36-877e-1d7aa1335dcd\",\"idpId\":53}";
    String formHtml = service.buildPostResponseForm(response, relayState, acsUrl);
    assertNotNull(formHtml);// w w w . j a va  2s  .com

    // find input attribute for RelayState in html post form, validate the expected RelayState is embedded in the form
    Pattern inputPattern = Pattern.compile("<input(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Pattern attributePattern = Pattern.compile("(\\w+)=\"(.*?)\"");
    Matcher inputPatternMatcher = inputPattern.matcher(formHtml);
    boolean relayStateFound = false;
    while (inputPatternMatcher.find()) {
        String attributesStr = inputPatternMatcher.group(1);
        Matcher attributePatternMatcher = attributePattern.matcher(attributesStr);
        while (attributePatternMatcher.find()) {
            if (attributePatternMatcher.group(1).equals("name")) {
                String key = attributePatternMatcher.group(2).trim();
                if (key.equals("RelayState")) {
                    attributePatternMatcher.find();
                    if (attributePatternMatcher.group(1).equals("value")) {
                        String value = StringEscapeUtils.unescapeHtml(attributePatternMatcher.group(2).trim());
                        assertEquals(relayState, value);
                        relayStateFound = true;
                        break;
                    }
                }
            }
        }
    }
    assertTrue(relayStateFound);
}

From source file:org.freeplane.plugin.script.ScriptingConfiguration.java

private static Pattern makeCaseInsensitivePattern(final String regexp) {
    return Pattern.compile(regexp, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
}

From source file:com.gs.obevo.db.apps.reveng.AquaRevengMain.java

private MutableList<ChangeEntry> calculateRevEngDest(DbPlatform dbPlatform, File file,
        String nameCombinePattern) {
    String[] fileNameParts = file.getName().split("\\.");
    String wholeFileString = FileUtilsCobra.readFileToString(file);
    String schema = fileNameParts[0];
    if (fileNameParts.length != 3) {
        if (!schema.equals("dbo") || fileNameParts.length != 5) {
            return Lists.mutable.with(new ChangeEntry(
                    new RevEngDestination(schema, UnclassifiedChangeType.INSTANCE, file.getName(), false),
                    wholeFileString, "n/a", null, 0));
        }//from   w w  w  .  j  a  v a2  s . co m
    }
    //public RevEngDestination(String content, ChangeType dbObjectType, String schema, String objectName,
    //boolean duplicate, int order) {

    ChangeTypeInfo contentObjectInfo = this.determineChangeType(wholeFileString);
    ChangeType objType = contentObjectInfo.getChangeType();
    String fileObjectName = this.getObjectNameFromFilename(fileNameParts[1], objType);

    // This is for cases in Sybase where teams had backed up db objects, and so it was created w/ a different name
    // in the object, but the underlying content points to the original name
    // We only fire off this check in case the scan of the content does pick up the object name, as to be
    // conservative
    // Addendum on 2014-10-15 - in case we know an object must be combined w/ another (e.g. index to parent),
    // we don't consider the object diff there as a duplicate
    boolean duplicate = dbPlatform.isDuplicateCheckRequiredForReverseEngineering()
            && !objType.getName().equals(ChangeType.INDEX_STR) && contentObjectInfo.getObjectName() != null
            && !contentObjectInfo.getObjectName().equalsIgnoreCase(fileObjectName);

    String objectName = contentObjectInfo.getObjectName() != null && !duplicate
            ? contentObjectInfo.getObjectName()
            : fileObjectName;

    String originalObjectName = objectName;

    objectName = extractName(objectName, nameCombinePattern);

    RevEngDestination dest = new RevEngDestination(schema, contentObjectInfo.getChangeType(), objectName,
            duplicate);

    // tokenize default schema name in the objects - this is only done if -tokenizeDefaultSchema is specified
    // on the command line
    if (this.tokenizeDefaultSchema) {
        wholeFileString = this.tokenizeDefaultSchema(schema, wholeFileString, objType, objectName);
    }

    MutableList<ChangeEntry> changes = Lists.mutable.empty();
    // handle any special overriding use cases if needed (currently not needed for view or sequence)
    if (objType.getName().equals(ChangeType.TABLE_STR)) {
        MutableList<String> statements = MultiLineStringSplitter.createSplitterOnSpaceAndLine("GO")
                .valueOf(wholeFileString);

        // append in tablespace if needed
        if (this.tablespaceToken) {
            statements.set(0, statements.get(0) + " IN ${" + schema.toUpperCase() + "_TABLESPACE" + "}");
        }

        PartitionMutableList<String> splitStatements = statements
                .partition(StringPredicates.contains("FOREIGN KEY"));
        MutableList<String> fkStatements = splitStatements.getSelected();
        final Pattern triggerPattern = Pattern.compile("(?i).*create.*trigger\\s+(\\w+)\r?\n.*",
                Pattern.DOTALL);
        splitStatements = splitStatements.getRejected().partition(new Predicate<String>() {
            @Override
            public boolean accept(String s) {
                return triggerPattern.matcher(s).matches();
            }
        });
        MutableList<String> triggerStatements = splitStatements.getSelected();

        final Pattern indexPattern = Pattern.compile("(?i).*create.*index\\s+(\\w+)\r?\n.*", Pattern.DOTALL);
        splitStatements = splitStatements.getRejected().partition(new Predicate<String>() {
            @Override
            public boolean accept(String s) {
                Matcher m = indexPattern.matcher(s);
                return m.matches();
            }
        });
        MutableList<String> indexStatements = splitStatements.getSelected();
        MutableList<String> nonFkStatements = splitStatements.getRejected();

        int selfOrder = 0;
        String endingString;
        if (nonFkStatements.isEmpty() || nonFkStatements.getLast().endsWith("GO")
                || StringUtils.isBlank(nonFkStatements.getLast())) {
            endingString = "\n";
        } else {
            endingString = "\nGO\n";
        }

        changes.add(new ChangeEntry(dest, nonFkStatements.makeString("\n", "\nGO\n", endingString), "init",
                null, selfOrder++));

        if (!fkStatements.isEmpty()) {
            changes.add(new ChangeEntry(dest,
                    fkStatements.collect(StringFunctions.trim()).makeString("", "\nGO\n", "\nGO\n"), "initFk",
                    "FK", selfOrder++));
        }
        for (String index : indexStatements) {
            Matcher m = indexPattern.matcher(index);
            if (m.matches()) {
                String indexName = m.group(1);
                changes.add(new ChangeEntry(dest, index.trim() + "\nGO", indexName, "INDEX", selfOrder++));
            } else {
                throw new IllegalStateException(
                        "Invalid state - this should have already had the index in it: " + index);
            }
        }
        for (String trigger : triggerStatements) {
            Matcher m = triggerPattern.matcher(trigger);
            if (m.matches()) {
                String name = m.group(1);
                changes.add(new ChangeEntry(dest, trigger.trim() + "\nGO", name, "TRIGGER", selfOrder++));
            } else {
                throw new IllegalStateException(
                        "Invalid state - this should have already had the trigger name in it: " + trigger);
            }
        }

        RichIterable<RuleBinding> ruleBindings = this.ruleBindingMap.get(objectName);
        if (ruleBindings != null) {
            int i = 1;
            for (RuleBinding binding : ruleBindings) {
                changes.add(new ChangeEntry(dest, binding.getSql().trim(), "binding" + i++, "FK", selfOrder++));
            }
        }
    } else if (objType.getName().equals(ChangeType.INDEX_STR)) {
        RevEngDestination newDest = new RevEngDestination(dest.getSchema(),
                dbPlatform.getChangeType(ChangeType.TABLE_STR), dest.getObjectName(), dest.isDuplicate());
        // the fileObjectName.replace line is to replace the file name w/ the object name in case it differs (e.g
        // . coalescing the different table files into one)
        changes.add(new ChangeEntry(newDest, wholeFileString.trim(),
                "index_" + fileObjectName.replace(originalObjectName, objectName), "INDEX", 100));
        //        } else if (objType == ChangeType.TRIGGER) {
        //
        //            RevEngDestination newDest = new RevEngDestination(dest.getSchema(), ChangeType.TABLE,
        //                    dest.getObjectName(), dest.isDuplicate());
        //            // the fileObjectName.replace line is to replace the file name w/ the object name in case it differs (e.g
        //            // . coalescing the different table files into one)
        //            changes.add(new ChangeEntry(newDest, wholeFileString.trim()
        //                    , "trigger_" + fileObjectName.replace(originalObjectName, objectName)
        //                    , "TRIGGER", 200));
    } else {
        RichIterable<RuleBinding> ruleBindings = this.ruleBindingMap.get(objectName);
        if (ruleBindings != null && !ruleBindings.isEmpty()) {
            for (RuleBinding binding : ruleBindings) {
                wholeFileString = wholeFileString + "\nGO\n" + binding.getSql().trim() + "\nGO";
            }
        }

        changes.add(new ChangeEntry(dest, wholeFileString));
    }

    dbPlatform.postProcessChangeForRevEng(changes.getFirst(), wholeFileString);

    return changes;
}

From source file:com.amalto.workbench.editors.StoredProcedureMainPage.java

protected void executeProcedure() {
    boolean checkMissingJar = MissingJarService.getInstance().checkMissingJar(true);
    if (!checkMissingJar) {
        return;/*w  ww.j  a  va  2  s . c  o  m*/
    }
    BusyIndicator.showWhile(this.getPartControl().getDisplay(), new Runnable() {

        public void run() {
            WSDataClusterPK dcpk = null;
            if (!"[ALL]".equals(dataClusterCombo.getText())) {
                dcpk = new WSDataClusterPK(dataClusterCombo.getText());
            }
            try {
                String proc = procedureViewer.getDocument().get();
                // read parameters
                int number = 0;

                while (true) {
                    Pattern p = Pattern.compile(".*[^\\\\]%" + number + "[^\\d]*.*", Pattern.DOTALL);//$NON-NLS-1$//$NON-NLS-2$
                    Matcher m = p.matcher(proc);
                    if (!m.matches()) {
                        break;
                    } else {
                        ++number;
                    }
                }
                String[] ps = null;
                if (number > 0) {
                    // transfer current parameters to new array
                    ps = new String[number];
                    for (int i = 0; i < number; i++) {
                        if (i < currentParameters.size()) {
                            ps[i] = currentParameters.get(i);
                        } else {
                            ps[i] = "";//$NON-NLS-1$
                        }
                    }
                    // call parameters window
                    QueryParametersDialog dialog = new QueryParametersDialog(
                            StoredProcedureMainPage.this.getSite().getShell(), ps);
                    dialog.setBlockOnOpen(true);
                    dialog.open();
                    if (dialog.getButtonPressed() == QueryParametersDialog.BUTTON_CANCEL) {
                        return;
                    }
                    ps = dialog.getParameters();
                    // Apply parameters
                    for (int i = 0; i < ps.length; i++) {
                        // transfer parameters back into current parameters
                        if (i < currentParameters.size()) {
                            currentParameters.set(i, ps[i]);
                        } else {
                            currentParameters.add(ps[i]);
                        }
                    }
                }
                // perform call
                TMDMService service = getMDMService();
                if (service != null) {
                    WSStoredProcedure wsStoredProcedure = (WSStoredProcedure) (getXObject().getWsObject());
                    service.putStoredProcedure(new WSPutStoredProcedure(wsStoredProcedure));
                    WSStringArray array = service.executeStoredProcedure(new WSExecuteStoredProcedure(
                            currentParameters, dcpk, new WSStoredProcedurePK(wsStoredProcedure.getName())));
                    List<String> results = array.getStrings();
                    resultsLabel.setText(Messages.StoredProcedureMainPage_15 + results.size()
                            + Messages.StoredProcedureMainPage_16);
                    resultsViewer.setInput(results);
                }
            } catch (Exception ex) {
                if (!Util.handleConnectionException(StoredProcedureMainPage.this.getSite().getShell(), ex,
                        null)) {
                    String message = ex.getMessage();
                    Set<String> messages = getMessages(message);
                    StringBuilder builder = new StringBuilder();
                    for (String currentMessage : messages) {
                        builder.append(currentMessage + '\n');
                    }
                    MessageDialog.openError(StoredProcedureMainPage.this.getSite().getShell(), Messages._Error,
                            builder.toString());
                }
            }
        }
    });
}

From source file:de.huberlin.wbi.hiway.am.galaxy.GalaxyApplicationMaster.java

/**
 * A helper function for parsing a Galaxy tool's XML file
 * //from w  w  w  . j a va  2  s.  c om
 * @param file
 *            the XML file to be parsed
 * @return the Galaxy tools described in the XML file
 */
private GalaxyTool parseToolFile(File file) {
    System.out.println("Parsing Galaxy tool file " + file);
    try {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        String path = file.getCanonicalPath();
        String dir = path.substring(0, path.lastIndexOf("/"));
        Document doc = builder.parse(file);
        Element rootEl = doc.getDocumentElement();
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        StreamResult result = new StreamResult(new StringWriter());
        DOMSource source = new DOMSource(rootEl);
        transformer.transform(source, result);
        String toolDescription = result.getWriter().toString();

        // (1) parse macros, if any
        NodeList macrosNds = rootEl.getElementsByTagName("macros");
        Map<String, String> macrosByName = new HashMap<>();
        for (int i = 0; i < macrosNds.getLength(); i++) {
            Node macrosNd = macrosNds.item(i);
            macrosByName.putAll(processMacros(macrosNd, dir));
        }

        // (2) insert macros into the XML and parse the document
        Pattern p = Pattern.compile("<expand macro=\"([^\"]*)\"(>.*?</expand>|/>)", Pattern.DOTALL);
        Matcher m = p.matcher(toolDescription);
        while (m.find()) {
            String name = m.group(1);
            String replace = m.group(0);
            String with = macrosByName.get(name);
            if (m.group(2).startsWith(">")) {
                String yield = m.group(2).substring(1, m.group(2).indexOf("</expand>"));
                with = with.replaceAll("<yield/>", yield.trim());
            }
            if (with != null)
                toolDescription = toolDescription.replace(replace, with);
        }

        doc = builder.parse(new InputSource(new StringReader(toolDescription)));
        rootEl = doc.getDocumentElement();
        String version = rootEl.hasAttribute("version") ? rootEl.getAttribute("version") : "1.0.0";
        String id = rootEl.getAttribute("id");
        GalaxyTool tool = new GalaxyTool(id, version, dir, galaxyPath);

        // (3) determine requirements (libraries and executables) of this tool; requirements have to be parsed such that the environment of the task can be
        // set to include them
        NodeList requirementNds = rootEl.getElementsByTagName("requirement");
        for (int i = 0; i < requirementNds.getLength(); i++) {
            Element requirementEl = (Element) requirementNds.item(i);
            String requirementName = requirementEl.getChildNodes().item(0).getNodeValue().trim();
            String requirementVersion = requirementEl.getAttribute("version");
            tool.addRequirement(requirementName, requirementVersion);
        }

        // (4) determine and set the template for the command of the task; this template will be compiled at runtime by Cheetah
        Element commandEl = (Element) rootEl.getElementsByTagName("command").item(0);
        if (commandEl != null) {
            String command = commandEl.getChildNodes().item(0).getNodeValue().trim();
            String script = command.split(" ")[0];
            String interpreter = commandEl.getAttribute("interpreter");
            if (interpreter.length() > 0) {
                command = command.replace(script, dir + "/" + script);
                command = interpreter + " " + command;
            }
            command = command.replaceAll("\\.value", "");
            command = command.replaceAll("\\.dataset", "");
            tool.setTemplate(command);
        }

        // (5) determine the parameters (atomic, conditional and repeat) of this tool
        Element inputsEl = (Element) rootEl.getElementsByTagName("inputs").item(0);
        if (inputsEl != null)
            tool.setParams(getParams(inputsEl, tool));

        // (6) determine the output files produced by this tool
        Element outputsEl = (Element) rootEl.getElementsByTagName("outputs").item(0);
        if (outputsEl != null) {
            NodeList dataNds = outputsEl.getElementsByTagName("data");
            for (int i = 0; i < dataNds.getLength(); i++) {
                Element dataEl = (Element) dataNds.item(i);
                String name = dataEl.getAttribute("name");
                GalaxyParamValue param = new GalaxyParamValue(name);
                tool.setPath(name);
                tool.addParam(param);

                String format = dataEl.getAttribute("format");
                String metadata_source = dataEl.getAttribute("metadata_source");
                if (format.equals("input") && metadata_source != null && metadata_source.length() > 0) {
                    param.setDataType(metadata_source);
                } else {
                    param.setDataType(format);
                }

                String from_work_dir = dataEl.getAttribute("from_work_dir");
                param.setFrom_work_dir(from_work_dir);
            }
        }

        // (7) register the tool in the Galaxy tool data structure
        if (tool.getTemplate() != null) {
            Map<String, GalaxyTool> toolMap = addAndGetToolMap(id);
            toolMap.put(version, tool);
        }

        return tool;
    } catch (SAXException | IOException | TransformerException | XPathExpressionException
            | ParserConfigurationException e) {
        e.printStackTrace();
        System.exit(-1);
        return null;
    }
}

From source file:org.encuestame.core.util.HTMLInputFilter.java

protected String validateEntities(String s) {
    // validate entities throughout the string
    Pattern pattern = Pattern.compile("&([^&;]*)(?=(;|&|$))");
    Matcher matcher = pattern.matcher(s);
    if (matcher.find()) {
        String one = matcher.group(1); // ([^&;]*)
        String two = matcher.group(2); // (?=(;|&|$))
        s = checkEntity(one, two);/*from  w  ww.j a va 2s  . co  m*/
    }

    // validate quotes outside of tags
    pattern = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
    matcher = pattern.matcher(s);
    StringBuffer buf = new StringBuffer();
    if (matcher.find()) {
        String one = matcher.group(1); // (>|^)
        String two = matcher.group(2); // ([^<]+?)
        String three = matcher.group(3); // (<|$)
        matcher.appendReplacement(buf, one + two.replaceAll("\"", "&quot;") + three);
    }
    matcher.appendTail(buf);

    return s;
}

From source file:org.apache.asterix.test.aql.TestExecutor.java

public void runScriptAndCompareWithResultRegex(File scriptFile, File expectedFile, File actualFile)
        throws Exception {
    System.err.println("Expected results file: " + expectedFile.toString());
    String lineExpected, lineActual;
    int num = 1;/* www.j  av a 2s  .  co  m*/
    try (BufferedReader readerExpected = new BufferedReader(
            new InputStreamReader(new FileInputStream(expectedFile), "UTF-8"));
            BufferedReader readerActual = new BufferedReader(
                    new InputStreamReader(new FileInputStream(actualFile), "UTF-8"))) {
        StringBuilder actual = new StringBuilder();
        while ((lineActual = readerActual.readLine()) != null) {
            actual.append(lineActual).append('\n');
        }
        while ((lineExpected = readerExpected.readLine()) != null) {
            if ("".equals(lineExpected.trim())) {
                continue;
            }
            Matcher m = REGEX_LINES_PATTERN.matcher(lineExpected);
            if (!m.matches()) {
                throw new IllegalArgumentException(
                        "Each line of regex file must conform to: [-]/regex/[flags]: " + expectedFile);
            }
            String negateStr = m.group(1);
            String expression = m.group(2);
            String flagStr = m.group(3);
            boolean negate = "-".equals(negateStr);
            int flags = Pattern.MULTILINE;
            if (flagStr.contains("m")) {
                flags |= Pattern.DOTALL;
            }
            if (flagStr.contains("i")) {
                flags |= Pattern.CASE_INSENSITIVE;
            }
            Pattern linePattern = Pattern.compile(expression, flags);
            boolean match = linePattern.matcher(actual).find();
            if (match && !negate || negate && !match) {
                continue;
            }
            throw new Exception("Result for " + scriptFile + ": expected pattern '" + expression
                    + "' not found in result.");
        }
    } catch (Exception e) {
        System.err.println("Actual results file: " + actualFile.toString());
        throw e;
    }

}

From source file:net.pms.util.OpenSubtitle.java

/**
 * Attempt to return information from IMDb about the file based on information
 * from the filename; either the hash, the IMDb ID or the filename itself.
 *
 * @param hash  the video hash/*from   w w  w  .  ja v  a  2 s  .  com*/
 * @param size  the bytesize to be used with the hash
 * @param imdb  the IMDb ID
 * @param query the string to search IMDb for
 *
 * @return a string array including the IMDb ID, episode title, season number,
 *         episode number relative to the season, and the show name, or null
 *         if we couldn't find it on IMDb.
 *
 * @throws IOException
 */
private static String[] getInfo(String hash, long size, String imdb, String query, RendererConfiguration r)
        throws IOException {
    if (!login()) {
        return null;
    }
    String lang = UMSUtils.getLangList(r, true);
    URL url = new URL(OPENSUBS_URL);
    String hashStr = "";
    String imdbStr = "";
    String qStr = "";
    if (!StringUtils.isEmpty(hash)) {
        hashStr = "<member><name>moviehash</name><value><string>" + hash + "</string></value></member>\n"
                + "<member><name>moviebytesize</name><value><double>" + size + "</double></value></member>\n";
    } else if (!StringUtils.isEmpty(imdb)) {
        imdbStr = "<member><name>imdbid</name><value><string>" + imdb + "</string></value></member>\n";
    } else if (!StringUtils.isEmpty(query)) {
        qStr = "<member><name>query</name><value><string>" + query + "</string></value></member>\n";
    } else {
        return null;
    }
    String req = null;
    tokenLock.readLock().lock();
    try {
        req = "<methodCall>\n<methodName>SearchSubtitles</methodName>\n" + "<params>\n<param>\n<value><string>"
                + token + "</string></value>\n</param>\n"
                + "<param>\n<value>\n<array>\n<data>\n<value><struct><member><name>sublanguageid"
                + "</name><value><string>" + lang + "</string></value></member>" + hashStr + imdbStr + qStr
                + "\n" + "</struct></value></data>\n</array>\n</value>\n</param>"
                + "</params>\n</methodCall>\n";
    } finally {
        tokenLock.readLock().unlock();
    }
    Pattern re = Pattern.compile(".*IDMovieImdb</name>.*?<string>([^<]+)</string>.*?" + ""
            + "MovieName</name>.*?<string>([^<]+)</string>.*?"
            + "SeriesSeason</name>.*?<string>([^<]+)</string>.*?"
            + "SeriesEpisode</name>.*?<string>([^<]+)</string>.*?"
            + "MovieYear</name>.*?<string>([^<]+)</string>.*?", Pattern.DOTALL);
    String page = postPage(url.openConnection(), req);
    Matcher m = re.matcher(page);
    if (m.find()) {
        LOGGER.debug("match " + m.group(1) + "," + m.group(2) + "," + m.group(3) + "," + m.group(4) + ","
                + m.group(5));
        Pattern re1 = Pattern.compile("&#34;([^&]+)&#34;(.*)");
        String name = m.group(2);
        Matcher m1 = re1.matcher(name);
        String eptit = "";
        if (m1.find()) {
            eptit = m1.group(2).trim();
            name = m1.group(1).trim();
        }

        return new String[] { ImdbUtil.ensureTT(m.group(1).trim()), StringEscapeUtils.unescapeHtml4(eptit),
                StringEscapeUtils.unescapeHtml4(name), m.group(3).trim(), // Season number
                m.group(4).trim(), // Episode number
                m.group(5).trim() // Year
        };
    }
    return null;
}

From source file:com.nttec.everychan.http.recaptcha.Recaptcha2fallback.java

@Override
public void handle(final Activity activity, final CancellableTask task, final Callback callback) {
    try {//from w  ww.  ja  va2s  .  c o  m
        final HttpClient httpClient = ((HttpChanModule) MainApplication.getInstance().getChanModule(chanName))
                .getHttpClient();
        final String usingURL = scheme + RECAPTCHA_FALLBACK_URL + publicKey
                + (sToken != null && sToken.length() > 0 ? ("&stoken=" + sToken) : "");
        String refererURL = baseUrl != null && baseUrl.length() > 0 ? baseUrl : usingURL;
        Header[] customHeaders = new Header[] { new BasicHeader(HttpHeaders.REFERER, refererURL) };
        String htmlChallenge;
        if (lastChallenge != null && lastChallenge.getLeft().equals(usingURL)) {
            htmlChallenge = lastChallenge.getRight();
        } else {
            htmlChallenge = HttpStreamer.getInstance().getStringFromUrl(usingURL,
                    HttpRequestModel.builder().setGET().setCustomHeaders(customHeaders).build(), httpClient,
                    null, task, false);
        }
        lastChallenge = null;

        Matcher challengeMatcher = Pattern.compile("name=\"c\" value=\"([\\w-]+)").matcher(htmlChallenge);
        if (challengeMatcher.find()) {
            final String challenge = challengeMatcher.group(1);
            HttpResponseModel responseModel = HttpStreamer.getInstance().getFromUrl(
                    scheme + RECAPTCHA_IMAGE_URL + challenge + "&k=" + publicKey,
                    HttpRequestModel.builder().setGET().setCustomHeaders(customHeaders).build(), httpClient,
                    null, task);
            try {
                InputStream imageStream = responseModel.stream;
                final Bitmap challengeBitmap = BitmapFactory.decodeStream(imageStream);

                final String message;
                Matcher messageMatcher = Pattern.compile("imageselect-message(?:.*?)>(.*?)</div>")
                        .matcher(htmlChallenge);
                if (messageMatcher.find())
                    message = RegexUtils.removeHtmlTags(messageMatcher.group(1));
                else
                    message = null;

                final Bitmap candidateBitmap;
                Matcher candidateMatcher = Pattern
                        .compile("fbc-imageselect-candidates(?:.*?)src=\"data:image/(?:.*?);base64,([^\"]*)\"")
                        .matcher(htmlChallenge);
                if (candidateMatcher.find()) {
                    Bitmap bmp = null;
                    try {
                        byte[] imgData = Base64.decode(candidateMatcher.group(1), Base64.DEFAULT);
                        bmp = BitmapFactory.decodeByteArray(imgData, 0, imgData.length);
                    } catch (Exception e) {
                    }
                    candidateBitmap = bmp;
                } else
                    candidateBitmap = null;

                activity.runOnUiThread(new Runnable() {
                    final int maxX = 3;
                    final int maxY = 3;
                    final boolean[] isSelected = new boolean[maxX * maxY];

                    @SuppressLint("InlinedApi")
                    @Override
                    public void run() {
                        LinearLayout rootLayout = new LinearLayout(activity);
                        rootLayout.setOrientation(LinearLayout.VERTICAL);

                        if (candidateBitmap != null) {
                            ImageView candidateView = new ImageView(activity);
                            candidateView.setImageBitmap(candidateBitmap);
                            int picSize = (int) (activity.getResources().getDisplayMetrics().density * 50
                                    + 0.5f);
                            candidateView.setLayoutParams(new LinearLayout.LayoutParams(picSize, picSize));
                            candidateView.setScaleType(ImageView.ScaleType.FIT_XY);
                            rootLayout.addView(candidateView);
                        }

                        if (message != null) {
                            TextView textView = new TextView(activity);
                            textView.setText(message);
                            CompatibilityUtils.setTextAppearance(textView, android.R.style.TextAppearance);
                            textView.setLayoutParams(
                                    new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                                            LinearLayout.LayoutParams.WRAP_CONTENT));
                            rootLayout.addView(textView);
                        }

                        FrameLayout frame = new FrameLayout(activity);
                        frame.setLayoutParams(
                                new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                                        LinearLayout.LayoutParams.WRAP_CONTENT));

                        final ImageView imageView = new ImageView(activity);
                        imageView.setLayoutParams(new FrameLayout.LayoutParams(
                                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
                        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                        imageView.setImageBitmap(challengeBitmap);
                        frame.addView(imageView);

                        final LinearLayout selector = new LinearLayout(activity);
                        selector.setLayoutParams(new FrameLayout.LayoutParams(
                                FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
                        AppearanceUtils.callWhenLoaded(imageView, new Runnable() {
                            @Override
                            public void run() {
                                selector.setLayoutParams(new FrameLayout.LayoutParams(imageView.getWidth(),
                                        imageView.getHeight()));
                            }
                        });
                        selector.setOrientation(LinearLayout.VERTICAL);
                        selector.setWeightSum(maxY);
                        for (int y = 0; y < maxY; ++y) {
                            LinearLayout subSelector = new LinearLayout(activity);
                            subSelector.setLayoutParams(new LinearLayout.LayoutParams(
                                    LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f));
                            subSelector.setOrientation(LinearLayout.HORIZONTAL);
                            subSelector.setWeightSum(maxX);
                            for (int x = 0; x < maxX; ++x) {
                                FrameLayout switcher = new FrameLayout(activity);
                                switcher.setLayoutParams(new LinearLayout.LayoutParams(0,
                                        LinearLayout.LayoutParams.MATCH_PARENT, 1f));
                                switcher.setTag(new int[] { x, y });
                                switcher.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        int[] coord = (int[]) v.getTag();
                                        int index = coord[1] * maxX + coord[0];
                                        isSelected[index] = !isSelected[index];
                                        v.setBackgroundColor(isSelected[index] ? Color.argb(128, 0, 255, 0)
                                                : Color.TRANSPARENT);
                                    }
                                });
                                subSelector.addView(switcher);
                            }
                            selector.addView(subSelector);
                        }

                        frame.addView(selector);
                        rootLayout.addView(frame);

                        Button checkButton = new Button(activity);
                        checkButton.setLayoutParams(
                                new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                                        LinearLayout.LayoutParams.WRAP_CONTENT));
                        checkButton.setText(android.R.string.ok);
                        rootLayout.addView(checkButton);

                        ScrollView dlgView = new ScrollView(activity);
                        dlgView.addView(rootLayout);

                        final Dialog dialog = new Dialog(activity);
                        dialog.setTitle("Recaptcha");
                        dialog.setContentView(dlgView);
                        dialog.setCanceledOnTouchOutside(false);
                        dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialog) {
                                if (!task.isCancelled()) {
                                    callback.onError("Cancelled");
                                }
                            }
                        });
                        dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT);
                        dialog.show();

                        checkButton.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                dialog.dismiss();
                                if (task.isCancelled())
                                    return;
                                Async.runAsync(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            List<NameValuePair> pairs = new ArrayList<NameValuePair>();
                                            pairs.add(new BasicNameValuePair("c", challenge));
                                            for (int i = 0; i < isSelected.length; ++i)
                                                if (isSelected[i])
                                                    pairs.add(new BasicNameValuePair("response",
                                                            Integer.toString(i)));

                                            HttpRequestModel request = HttpRequestModel.builder()
                                                    .setPOST(new UrlEncodedFormEntity(pairs, "UTF-8"))
                                                    .setCustomHeaders(new Header[] {
                                                            new BasicHeader(HttpHeaders.REFERER, usingURL) })
                                                    .build();
                                            String response = HttpStreamer.getInstance().getStringFromUrl(
                                                    usingURL, request, httpClient, null, task, false);
                                            String hash = "";
                                            Matcher matcher = Pattern.compile(
                                                    "fbc-verification-token(?:.*?)<textarea[^>]*>([^<]*)<",
                                                    Pattern.DOTALL).matcher(response);
                                            if (matcher.find())
                                                hash = matcher.group(1);

                                            if (hash.length() > 0) {
                                                Recaptcha2solved.push(publicKey, hash);
                                                activity.runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        callback.onSuccess();
                                                    }
                                                });
                                            } else {
                                                lastChallenge = Pair.of(usingURL, response);
                                                throw new RecaptchaException(
                                                        "incorrect answer (hash is empty)");
                                            }
                                        } catch (final Exception e) {
                                            Logger.e(TAG, e);
                                            if (task.isCancelled())
                                                return;
                                            handle(activity, task, callback);
                                        }
                                    }
                                });
                            }
                        });
                    }
                });
            } finally {
                responseModel.release();
            }
        } else
            throw new Exception("can't parse recaptcha challenge answer");
    } catch (final Exception e) {
        Logger.e(TAG, e);
        if (!task.isCancelled()) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    callback.onError(e.getMessage() != null ? e.getMessage() : e.toString());
                }
            });
        }
    }
}