Example usage for org.apache.commons.httpclient URI getScheme

List of usage examples for org.apache.commons.httpclient URI getScheme

Introduction

In this page you can find the example usage for org.apache.commons.httpclient URI getScheme.

Prototype

public String getScheme() 

Source Link

Document

Get the scheme.

Usage

From source file:com.eviware.soapui.impl.support.HttpUtils.java

public static java.net.URI createUri(URI uri) throws URISyntaxException, URIException {
    return createUri(uri.getScheme(), uri.getUserinfo(), uri.getHost(), uri.getPort(), uri.getEscapedPath(),
            uri.getEscapedQuery(), uri.getEscapedFragment());
}

From source file:com.limegroup.gnutella.licenses.LicenseFactory.java

/** Gets a CC license URI from the given license string. */
private static URI getCCLicenseURI(String license) {
    // find where the URL should begin.
    int verifyAt = license.indexOf(CCConstants.URL_INDICATOR);
    if (verifyAt == -1)
        return null;

    int urlStart = verifyAt + CCConstants.URL_INDICATOR.length();
    if (urlStart >= license.length())
        return null;

    String url = license.substring(urlStart).trim();
    URI uri = null;
    try {//from  ww  w .java 2  s. c o m
        uri = new URI(url.toCharArray());

        // Make sure the scheme is HTTP.
        String scheme = uri.getScheme();
        if (scheme == null || !scheme.equalsIgnoreCase("http"))
            throw new URIException("Invalid scheme: " + scheme);
        // Make sure the scheme has some authority.
        String authority = uri.getAuthority();
        if (authority == null || authority.equals("") || authority.indexOf(' ') != -1)
            throw new URIException("Invalid authority: " + authority);

    } catch (URIException e) {
        uri = null;
        LOG.error("Unable to create URI", e);
    }

    return uri;
}

From source file:com.eviware.soapui.impl.wsdl.submit.filters.EndpointRequestFilter.java

@Override
public void filterAbstractHttpRequest(SubmitContext context, AbstractHttpRequest<?> request) {
    HttpRequestBase httpMethod = (HttpRequestBase) context.getProperty(BaseHttpRequestTransport.HTTP_METHOD);

    String strURL = request.getEndpoint();
    strURL = PropertyExpander.expandProperties(context, strURL);
    try {//ww  w .j a v a  2  s .  co m
        if (StringUtils.hasContent(strURL)) {
            URI uri = new URI(strURL, request.getSettings().getBoolean(HttpSettings.ENCODED_URLS));
            context.setProperty(BaseHttpRequestTransport.REQUEST_URI, uri);
            httpMethod.setURI(new java.net.URI(uri.getScheme(), uri.getUserinfo(), uri.getHost(), uri.getPort(),
                    (uri.getPath()) == null ? "/" : uri.getPath(), uri.getQuery(), uri.getFragment()));
        }
    } catch (Exception e) {
        SoapUI.logError(e);
    }
}

From source file:com.eviware.soapui.impl.wsdl.submit.transports.http.HttpClientRequestTransport.java

private ExtendedGetMethod followRedirects(HttpClient httpClient, int redirectCount,
        ExtendedHttpMethod httpMethod, org.apache.http.HttpResponse httpResponse, HttpContext httpContext)
        throws Exception {
    ExtendedGetMethod getMethod = new ExtendedGetMethod();

    getMethod.getMetrics().getTotalTimer().set(httpMethod.getMetrics().getTotalTimer().getStart(),
            httpMethod.getMetrics().getTotalTimer().getStop());
    getMethod.getMetrics().setHttpMethod(httpMethod.getMethod());
    captureMetrics(httpMethod, httpClient);

    String location = httpResponse.getFirstHeader("Location").getValue();
    URI uri = new URI(new URI(httpMethod.getURI().toString(), true), location, true);
    java.net.URI newUri = new java.net.URI(uri.getScheme(), uri.getUserinfo(), uri.getHost(), uri.getPort(),
            uri.getPath(), uri.getQuery(), uri.getFragment());
    getMethod.setURI(newUri);/*from  www . j  a v a  2s .co  m*/

    org.apache.http.HttpResponse response = HttpClientSupport.execute(getMethod, httpContext);

    if (isRedirectResponse(response.getStatusLine().getStatusCode())) {
        if (redirectCount == 10)
            throw new Exception("Maximum number of Redirects reached [10]");

        try {
            getMethod = followRedirects(httpClient, redirectCount + 1, getMethod, response, httpContext);
        } finally {
            //getMethod.releaseConnection();
        }
    }

    for (Header header : httpMethod.getAllHeaders())
        getMethod.addHeader(header);

    return getMethod;
}

From source file:de.innovationgate.utils.URLBuilder.java

/**
 * Creates a URLBuilder that parses an existing URI
 * @param uri The URI to parse/* ww  w  .j  a  v  a  2 s. co  m*/
 */
public URLBuilder(URI uri) throws URIException {
    this(uri.getScheme(), uri.getPort(), uri.getHost(), uri.getPath(), uri.getQuery(), uri.getFragment(),
            "UTF-8");
}

From source file:de.innovationgate.utils.URLBuilder.java

/**
 * Creates a URLBuilder that parses an existing URI
 * @param uri The URI to parse/* w  ww  .  j a v  a  2 s. c o  m*/
 * @param encoding The encoding of URL parameters. The URLBuilder will decode them.
 */
public URLBuilder(URI uri, String encoding) throws URIException {
    this(uri.getScheme(), uri.getPort(), uri.getHost(), uri.getPath(), uri.getQuery(), uri.getFragment(),
            encoding);
}

From source file:com.eviware.soapui.impl.wsdl.submit.filters.HttpRequestFilter.java

@SuppressWarnings("deprecation")
@Override//from  www .  j  ava 2 s  .  co m
public void filterHttpRequest(SubmitContext context, HttpRequestInterface<?> request) {
    HttpRequestBase httpMethod = (HttpRequestBase) context.getProperty(BaseHttpRequestTransport.HTTP_METHOD);

    String path = PropertyExpander.expandProperties(context, request.getPath());
    StringBuffer query = new StringBuffer();
    String encoding = System.getProperty("soapui.request.encoding", StringUtils.unquote(request.getEncoding()));

    StringToStringMap responseProperties = (StringToStringMap) context
            .getProperty(BaseHttpRequestTransport.RESPONSE_PROPERTIES);

    MimeMultipart formMp = "multipart/form-data".equals(request.getMediaType())
            && httpMethod instanceof HttpEntityEnclosingRequestBase ? new MimeMultipart() : null;

    RestParamsPropertyHolder params = request.getParams();

    for (int c = 0; c < params.getPropertyCount(); c++) {
        RestParamProperty param = params.getPropertyAt(c);

        String value = PropertyExpander.expandProperties(context, param.getValue());
        responseProperties.put(param.getName(), value);

        List<String> valueParts = sendEmptyParameters(request)
                || (!StringUtils.hasContent(value) && param.getRequired())
                        ? RestUtils.splitMultipleParametersEmptyIncluded(value,
                                request.getMultiValueDelimiter())
                        : RestUtils.splitMultipleParameters(value, request.getMultiValueDelimiter());

        // skip HEADER and TEMPLATE parameter encoding (TEMPLATE is encoded by
        // the URI handling further down)
        if (value != null && param.getStyle() != ParameterStyle.HEADER
                && param.getStyle() != ParameterStyle.TEMPLATE && !param.isDisableUrlEncoding()) {
            try {
                if (StringUtils.hasContent(encoding)) {
                    value = URLEncoder.encode(value, encoding);
                    for (int i = 0; i < valueParts.size(); i++)
                        valueParts.set(i, URLEncoder.encode(valueParts.get(i), encoding));
                } else {
                    value = URLEncoder.encode(value);
                    for (int i = 0; i < valueParts.size(); i++)
                        valueParts.set(i, URLEncoder.encode(valueParts.get(i)));
                }
            } catch (UnsupportedEncodingException e1) {
                SoapUI.logError(e1);
                value = URLEncoder.encode(value);
                for (int i = 0; i < valueParts.size(); i++)
                    valueParts.set(i, URLEncoder.encode(valueParts.get(i)));
            }
            // URLEncoder replaces space with "+", but we want "%20".
            value = value.replaceAll("\\+", "%20");
            for (int i = 0; i < valueParts.size(); i++)
                valueParts.set(i, valueParts.get(i).replaceAll("\\+", "%20"));
        }

        if (param.getStyle() == ParameterStyle.QUERY && !sendEmptyParameters(request)) {
            if (!StringUtils.hasContent(value) && !param.getRequired())
                continue;
        }

        switch (param.getStyle()) {
        case HEADER:
            for (String valuePart : valueParts)
                httpMethod.addHeader(param.getName(), valuePart);
            break;
        case QUERY:
            if (formMp == null || !request.isPostQueryString()) {
                for (String valuePart : valueParts) {
                    if (query.length() > 0)
                        query.append('&');

                    query.append(URLEncoder.encode(param.getName()));
                    query.append('=');
                    if (StringUtils.hasContent(valuePart))
                        query.append(valuePart);
                }
            } else {
                try {
                    addFormMultipart(request, formMp, param.getName(), responseProperties.get(param.getName()));
                } catch (MessagingException e) {
                    SoapUI.logError(e);
                }
            }

            break;
        case TEMPLATE:
            try {
                value = getEncodedValue(value, encoding, param.isDisableUrlEncoding(),
                        request.getSettings().getBoolean(HttpSettings.ENCODED_URLS));
                path = path.replaceAll("\\{" + param.getName() + "\\}", value == null ? "" : value);
            } catch (UnsupportedEncodingException e) {
                SoapUI.logError(e);
            }
            break;
        case MATRIX:
            try {
                value = getEncodedValue(value, encoding, param.isDisableUrlEncoding(),
                        request.getSettings().getBoolean(HttpSettings.ENCODED_URLS));
            } catch (UnsupportedEncodingException e) {
                SoapUI.logError(e);
            }

            if (param.getType().equals(XmlBoolean.type.getName())) {
                if (value.toUpperCase().equals("TRUE") || value.equals("1")) {
                    path += ";" + param.getName();
                }
            } else {
                path += ";" + param.getName();
                if (StringUtils.hasContent(value)) {
                    path += "=" + value;
                }
            }
        case PLAIN:
            break;
        }
    }

    if (request.getSettings().getBoolean(HttpSettings.FORWARD_SLASHES))
        path = PathUtils.fixForwardSlashesInPath(path);

    if (PathUtils.isHttpPath(path)) {
        try {
            // URI(String) automatically URLencodes the input, so we need to
            // decode it first...
            URI uri = new URI(path, request.getSettings().getBoolean(HttpSettings.ENCODED_URLS));
            context.setProperty(BaseHttpRequestTransport.REQUEST_URI, uri);
            java.net.URI oldUri = httpMethod.getURI();
            httpMethod.setURI(new java.net.URI(oldUri.getScheme(), oldUri.getUserInfo(), oldUri.getHost(),
                    oldUri.getPort(), (uri.getPath()) == null ? "/" : uri.getPath(), oldUri.getQuery(),
                    oldUri.getFragment()));
        } catch (Exception e) {
            SoapUI.logError(e);
        }
    } else if (StringUtils.hasContent(path)) {
        try {
            java.net.URI oldUri = httpMethod.getURI();
            String pathToSet = StringUtils.hasContent(oldUri.getRawPath()) && !"/".equals(oldUri.getRawPath())
                    ? oldUri.getRawPath() + path
                    : path;
            java.net.URI newUri = URIUtils.createURI(oldUri.getScheme(), oldUri.getHost(), oldUri.getPort(),
                    pathToSet, oldUri.getQuery(), oldUri.getFragment());
            httpMethod.setURI(newUri);
            context.setProperty(BaseHttpRequestTransport.REQUEST_URI,
                    new URI(newUri.toString(), request.getSettings().getBoolean(HttpSettings.ENCODED_URLS)));
        } catch (Exception e) {
            SoapUI.logError(e);
        }
    }

    if (query.length() > 0 && !request.isPostQueryString()) {
        try {
            java.net.URI oldUri = httpMethod.getURI();
            httpMethod.setURI(URIUtils.createURI(oldUri.getScheme(), oldUri.getHost(), oldUri.getPort(),
                    oldUri.getRawPath(), query.toString(), oldUri.getFragment()));
        } catch (Exception e) {
            SoapUI.logError(e);
        }
    }

    if (request instanceof RestRequest) {
        String acceptEncoding = ((RestRequest) request).getAccept();
        if (StringUtils.hasContent(acceptEncoding)) {
            httpMethod.setHeader("Accept", acceptEncoding);
        }
    }

    if (formMp != null) {
        // create request message
        try {
            if (request.hasRequestBody() && httpMethod instanceof HttpEntityEnclosingRequest) {
                String requestContent = PropertyExpander.expandProperties(context, request.getRequestContent(),
                        request.isEntitizeProperties());
                if (StringUtils.hasContent(requestContent)) {
                    initRootPart(request, requestContent, formMp);
                }
            }

            for (Attachment attachment : request.getAttachments()) {
                MimeBodyPart part = new PreencodedMimeBodyPart("binary");

                if (attachment instanceof FileAttachment<?>) {
                    String name = attachment.getName();
                    if (StringUtils.hasContent(attachment.getContentID())
                            && !name.equals(attachment.getContentID()))
                        name = attachment.getContentID();

                    part.setDisposition(
                            "form-data; name=\"" + name + "\"; filename=\"" + attachment.getName() + "\"");
                } else
                    part.setDisposition("form-data; name=\"" + attachment.getName() + "\"");

                part.setDataHandler(new DataHandler(new AttachmentDataSource(attachment)));

                formMp.addBodyPart(part);
            }

            MimeMessage message = new MimeMessage(AttachmentUtils.JAVAMAIL_SESSION);
            message.setContent(formMp);
            message.saveChanges();
            RestRequestMimeMessageRequestEntity mimeMessageRequestEntity = new RestRequestMimeMessageRequestEntity(
                    message, request);
            ((HttpEntityEnclosingRequest) httpMethod).setEntity(mimeMessageRequestEntity);
            httpMethod.setHeader("Content-Type", mimeMessageRequestEntity.getContentType().getValue());
            httpMethod.setHeader("MIME-Version", "1.0");
        } catch (Throwable e) {
            SoapUI.logError(e);
        }
    } else if (request.hasRequestBody() && httpMethod instanceof HttpEntityEnclosingRequest) {
        if (StringUtils.hasContent(request.getMediaType()))
            httpMethod.setHeader("Content-Type", getContentTypeHeader(request.getMediaType(), encoding));

        if (request.isPostQueryString()) {
            try {
                ((HttpEntityEnclosingRequest) httpMethod).setEntity(new StringEntity(query.toString()));
            } catch (UnsupportedEncodingException e) {
                SoapUI.logError(e);
            }
        } else {
            String requestContent = PropertyExpander.expandProperties(context, request.getRequestContent(),
                    request.isEntitizeProperties());
            List<Attachment> attachments = new ArrayList<Attachment>();

            for (Attachment attachment : request.getAttachments()) {
                if (attachment.getContentType().equals(request.getMediaType())) {
                    attachments.add(attachment);
                }
            }

            if (StringUtils.hasContent(requestContent) && attachments.isEmpty()) {
                try {
                    byte[] content = encoding == null ? requestContent.getBytes()
                            : requestContent.getBytes(encoding);
                    ((HttpEntityEnclosingRequest) httpMethod).setEntity(new ByteArrayEntity(content));
                } catch (UnsupportedEncodingException e) {
                    ((HttpEntityEnclosingRequest) httpMethod)
                            .setEntity(new ByteArrayEntity(requestContent.getBytes()));
                }
            } else if (attachments.size() > 0) {
                try {
                    MimeMultipart mp = null;

                    if (StringUtils.hasContent(requestContent)) {
                        mp = new MimeMultipart();
                        initRootPart(request, requestContent, mp);
                    } else if (attachments.size() == 1) {
                        ((HttpEntityEnclosingRequest) httpMethod)
                                .setEntity(new InputStreamEntity(attachments.get(0).getInputStream(), -1));

                        httpMethod.setHeader("Content-Type",
                                getContentTypeHeader(request.getMediaType(), encoding));
                    }

                    if (((HttpEntityEnclosingRequest) httpMethod).getEntity() == null) {
                        if (mp == null)
                            mp = new MimeMultipart();

                        // init mimeparts
                        AttachmentUtils.addMimeParts(request, attachments, mp, new StringToStringMap());

                        // create request message
                        MimeMessage message = new MimeMessage(AttachmentUtils.JAVAMAIL_SESSION);
                        message.setContent(mp);
                        message.saveChanges();
                        RestRequestMimeMessageRequestEntity mimeMessageRequestEntity = new RestRequestMimeMessageRequestEntity(
                                message, request);
                        ((HttpEntityEnclosingRequest) httpMethod).setEntity(mimeMessageRequestEntity);
                        httpMethod.setHeader("Content-Type", getContentTypeHeader(
                                mimeMessageRequestEntity.getContentType().getValue(), encoding));
                        httpMethod.setHeader("MIME-Version", "1.0");
                    }
                } catch (Exception e) {
                    SoapUI.logError(e);
                }
            }
        }
    }
}

From source file:com.cyberway.issue.net.UURIFactory.java

/**
 * If http(s) scheme, check scheme specific part begins '//'.
 * @throws URIException /*  w ww  . ja v  a  2s.c  om*/
 * @see http://www.faqs.org/rfcs/rfc1738.html Section 3.1. Common Internet
 * Scheme Syntax
 */
protected void checkHttpSchemeSpecificPartSlashPrefix(final URI base, final String scheme,
        final String schemeSpecificPart) throws URIException {
    if (scheme == null || scheme.length() <= 0) {
        return;
    }
    if (!scheme.equals("http") && !scheme.equals("https")) {
        return;
    }
    if (schemeSpecificPart == null || !schemeSpecificPart.startsWith("//")) {
        // only acceptable if schemes match
        if (base == null || !scheme.equals(base.getScheme())) {
            throw new URIException("relative URI with scheme only allowed for " + "scheme matching base");
        }
        return;
    }
    if (schemeSpecificPart.length() <= 2) {
        throw new URIException("http scheme specific part is " + "too short: " + schemeSpecificPart);
    }
}

From source file:com.twinsoft.convertigo.beans.connectors.HttpConnector.java

private String getAbsoluteUrl(HttpMethod method, String givenUrl)
        throws URIException, MalformedURLException, EngineException {
    String absoluteUrl = givenUrl;
    if (method != null) {
        if (givenUrl != null) {
            // givenUrl is already absolute
            if (givenUrl.startsWith("http")) {
                absoluteUrl = givenUrl;//  w  ww  . j  ava 2 s.c om

                URL url = null;
                String host = "";
                int port = -1;
                if (absoluteUrl.toLowerCase().startsWith("https:")) {
                    if (!https) {
                        Engine.logBeans.debug("(HttpConnector) Setting up SSL properties");
                        certificateManager.collectStoreInformation(context);
                    }

                    url = new URL(absoluteUrl);
                    host = url.getHost();
                    port = url.getPort();
                    if (port == -1)
                        port = 443;

                    Engine.logBeans.debug("(HttpConnector) Host: " + host + ":" + port);

                    Engine.logBeans.debug(
                            "(HttpConnector) CertificateManager has changed: " + certificateManager.hasChanged);
                    if (certificateManager.hasChanged || (!host.equalsIgnoreCase(hostConfiguration.getHost()))
                            || (hostConfiguration.getPort() != port)) {
                        Engine.logBeans
                                .debug("(HttpConnector) Using MySSLSocketFactory for creating the SSL socket");
                        Protocol myhttps = new Protocol("https",
                                MySSLSocketFactory.getSSLSocketFactory(certificateManager.keyStore,
                                        certificateManager.keyStorePassword, certificateManager.trustStore,
                                        certificateManager.trustStorePassword, this.trustAllServerCertificates),
                                port);

                        hostConfiguration.setHost(host, port, myhttps);
                    }

                    // absoluteUrl = url.getFile();
                    Engine.logBeans.debug("(HttpConnector) Updated URL for SSL purposes: " + absoluteUrl);
                } else {
                    url = new URL(absoluteUrl);
                    host = url.getHost();
                    port = url.getPort();

                    Engine.logBeans.debug("(HttpConnector) Host: " + host + ":" + port);
                    hostConfiguration.setHost(host, port);
                }
            }
            // givenUrl is relative to method uri ones
            else {
                URI uri = method.getURI();
                String methodProtocol = uri.getScheme();
                String methodHost = uri.getHost();

                if (hostConfiguration.getProtocol().isSecure()) {
                    return givenUrl.startsWith("/") ? givenUrl : ('/' + givenUrl);
                }

                int methodPort = uri.getPort();
                String path = uri.getCurrentHierPath();
                path = ((path.equals("/") ? "" : path));

                absoluteUrl = methodProtocol + "://" + methodHost;
                if (methodPort != -1) {
                    absoluteUrl += ":" + methodPort;
                }

                if (!givenUrl.startsWith("/") && (path.length() == 0 || !givenUrl.contains(path + "/"))) {
                    absoluteUrl += path + "/" + givenUrl;
                } else {
                    absoluteUrl += givenUrl;
                }
            }
        }
    }
    return absoluteUrl;
}

From source file:de.kimminich.agile.demos.lecture4.TestSQLInjection.java

/**
 * scans for SQL Injection vulnerabilities
 *///w  w  w.  jav  a  2  s. com
@Override
public void scan(HttpMessage msg, String param, String origParamValue) {
    //Note: the "value" we are passed here is escaped. we need to unescape it before handling it.
    //as soon as we find a single SQL injection on the url, skip out. Do not look for SQL injection on a subsequent parameter on the same URL
    //for performance reasons.
    boolean sqlInjectionFoundForUrl = false;
    String sqlInjectionAttack = null;
    HttpMessage refreshedmessage = null;
    String mResBodyNormalUnstripped = null;
    String mResBodyNormalStripped = null;

    try {

        //reinitialise the count for each type of request, for each parameter.  We will be sticking to limits defined in the attach strength logic
        int countErrorBasedRequests = 0;
        int countExpressionBasedRequests = 0;
        int countBooleanBasedRequests = 0;
        int countUnionBasedRequests = 0;
        int countOrderByBasedRequests = 0;
        int countStackedBasedRequests = 0; //TODO: use in the stacked based queries implementation

        //Check 1: Check for Error Based SQL Injection (actual error messages).
        //for each SQL metacharacter combination to try
        for (int sqlErrorStringIndex = 0; sqlErrorStringIndex < SQL_CHECK_ERR.length && !sqlInjectionFoundForUrl
                && doErrorBased && countErrorBasedRequests < doErrorMaxRequests; sqlErrorStringIndex++) {

            //work through the attack using each of the following strings as a prefix: the empty string, and the original value
            //Note: this doubles the amount of work done by the scanner, but is necessary in some cases
            String[] prefixStrings;
            if (origParamValue != null) {
                prefixStrings = new String[] { "", TestSQLInjection.getURLDecode(origParamValue) };
            } else {
                prefixStrings = new String[] { "" };
            }
            for (int prefixIndex = 0; prefixIndex < prefixStrings.length; prefixIndex++) {

                //new message for each value we attack with
                HttpMessage msg1 = getNewMsg();
                String sqlErrValue = prefixStrings[prefixIndex] + SQL_CHECK_ERR[sqlErrorStringIndex];
                setParameter(msg1, param, sqlErrValue);

                //System.out.println("Attacking [" + msg + "], parameter [" + param + "] with value ["+ sqlErrValue + "]");

                //send the message with the modified parameters
                sendAndReceive(msg1);
                countErrorBasedRequests++;

                //now check the results against each pattern in turn, to try to identify a database, or even better: a specific database.
                //Note: do NOT check the HTTP error code just yet, as the result could come back with one of various codes.
                Iterator<String> errorPatternIterator = SQL_ERROR_TO_DBMS.keySet().iterator();

                while (errorPatternIterator.hasNext() && !sqlInjectionFoundForUrl) {
                    String errorPatternKey = errorPatternIterator.next();
                    String errorPatternRDBMS = SQL_ERROR_TO_DBMS.get(errorPatternKey);

                    //Note: must escape the strings, in case they contain strings like "[Microsoft], which would be interpreted as regular character class regexps"
                    Pattern errorPattern = Pattern.compile("\\Q" + errorPatternKey + "\\E", PATTERN_PARAM);

                    //if the "error message" occurs in the result of sending the modified query, but did NOT occur in the original result of the original query
                    //then we may may have a SQL Injection vulnerability
                    StringBuilder sb = new StringBuilder();
                    if (!matchBodyPattern(getBaseMsg(), errorPattern, null)
                            && matchBodyPattern(msg1, errorPattern, sb)) {
                        //Likely a SQL Injection. Raise it
                        String extraInfo = Constant.messages.getString(
                                "ascanrules.sqlinjection.alert.errorbased.extrainfo", errorPatternRDBMS,
                                errorPatternKey);
                        //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                        sqlInjectionAttack = sqlErrValue;
                        bingo(Alert.RISK_HIGH, Alert.WARNING, getName() + " - " + errorPatternRDBMS,
                                getDescription(), null, param, sqlInjectionAttack, extraInfo, getSolution(),
                                msg1);

                        //log it, as the RDBMS may be useful to know later (in subsequent checks, when we need to determine RDBMS specific behaviour, for instance)
                        getKb().add(getBaseMsg().getRequestHeader().getURI(), "sql/" + errorPatternRDBMS,
                                Boolean.TRUE);

                        sqlInjectionFoundForUrl = true;
                        continue;
                    }
                } //end of the loop to check for RDBMS specific error messages

            } //for each of the SQL_CHECK_ERR values (SQL metacharacters)
        }

        //###############################
        //Check 4
        //New!  I haven't seen this technique documented anywhere else, but it's dead simple. Let me explain.
        //See if the parameter value can simply be changed to one that *evaluates* to be the same value,
        //if evaluated on a database
        //the simple check is to see if parameter "1" gives the same results as for param "2-1", and different results for param "2-2"
        //for now, we try this for integer values only.
        //###############################
        //Since the previous checks are attempting SQL injection, and may have actually succeeded in modifying the database (ask me how I know?!)
        //then we cannot rely on the database contents being the same as when the original query was last run (could be hours ago)
        //so to work around this, simply re-run the query again now at this point.
        //Note that we are not counting this request in our max number of requests to be issued
        refreshedmessage = getNewMsg();
        sendAndReceive(refreshedmessage);

        //String mResBodyNormal = getBaseMsg().getResponseBody().toString();
        mResBodyNormalUnstripped = refreshedmessage.getResponseBody().toString();
        mResBodyNormalStripped = this.stripOff(mResBodyNormalUnstripped, origParamValue);

        if (!sqlInjectionFoundForUrl && doExpressionBased
                && countExpressionBasedRequests < doExpressionMaxRequests) {

            //first figure out the type of the parameter..
            try {
                //is it an integer type?
                int paramAsInt = new Integer(TestSQLInjection.getURLDecode(origParamValue));
                if (this.debugEnabled)
                    log.debug("The parameter value [" + TestSQLInjection.getURLDecode(origParamValue)
                            + "] is of type Integer");

                //get a value 2 sizes bigger
                int paramPlusTwo = paramAsInt + 2;
                String modifiedParamValue = String.valueOf(paramPlusTwo) + "-2";

                //and prepare a request to set the parameter value to a string value like "3-2", if the original parameter value was "1"
                //those of you still paying attention will note that if handled as expressions (such as by a database), these represent the same value.
                HttpMessage msg4 = getNewMsg();
                setParameter(msg4, param, modifiedParamValue);

                sendAndReceive(msg4);
                countExpressionBasedRequests++;

                String modifiedExpressionOutputUnstripped = msg4.getResponseBody().toString();
                String modifiedExpressionOutputStripped = this.stripOff(modifiedExpressionOutputUnstripped,
                        modifiedParamValue);

                //set up two little arrays to ease the work of checking the unstripped output, and then the stripped output
                String normalBodyOutput[] = { mResBodyNormalUnstripped, mResBodyNormalStripped };
                String expressionBodyOutput[] = { modifiedExpressionOutputUnstripped,
                        modifiedExpressionOutputStripped };
                boolean strippedOutput[] = { false, true };

                for (int booleanStrippedUnstrippedIndex = 0; booleanStrippedUnstrippedIndex < 2; booleanStrippedUnstrippedIndex++) {
                    //if the results of the modified request match the original query, we may be onto something.
                    if (expressionBodyOutput[booleanStrippedUnstrippedIndex]
                            .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) == 0) {
                        if (this.debugEnabled)
                            log.debug("Check 4, "
                                    + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                            : "UNSTRIPPED")
                                    + " html output for modified expression parameter [" + modifiedParamValue
                                    + "] matched (refreshed) original results for "
                                    + refreshedmessage.getRequestHeader().getURI());
                        //confirm that a different parameter value generates different output, to minimise false positives

                        //get a value 3 sizes bigger this time
                        int paramPlusFour = paramAsInt + 3;
                        String modifiedParamValueConfirm = String.valueOf(paramPlusFour) + "-2";

                        //and prepare a request to set the parameter value to a string value like "4-2", if the original parameter value was "1"
                        //Note that the two values are NOT equivalent, and the param value is different to the original
                        HttpMessage msg4Confirm = getNewMsg();
                        setParameter(msg4Confirm, param, modifiedParamValueConfirm);

                        sendAndReceive(msg4Confirm);
                        countExpressionBasedRequests++;

                        String confirmExpressionOutputUnstripped = msg4Confirm.getResponseBody().toString();
                        String confirmExpressionOutputStripped = this
                                .stripOff(confirmExpressionOutputUnstripped, modifiedParamValueConfirm);

                        //set up two little arrays to ease the work of checking the unstripped output or the stripped output
                        String confirmExpressionBodyOutput[] = { confirmExpressionOutputUnstripped,
                                confirmExpressionOutputStripped };

                        if (confirmExpressionBodyOutput[booleanStrippedUnstrippedIndex]
                                .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) {
                            //the confirm query did not return the same results.  This means that arbitrary queries are not all producing the same page output.
                            //this means the fact we earier reproduced the original page output with a modified parameter was not a coincidence

                            //Likely a SQL Injection. Raise it
                            String extraInfo = null;
                            if (strippedOutput[booleanStrippedUnstrippedIndex])
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.expressionbased.extrainfo",
                                        modifiedParamValue, "");
                            else
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.expressionbased.extrainfo",
                                        modifiedParamValue, "NOT ");

                            //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                            sqlInjectionAttack = modifiedParamValue;
                            bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                    param, sqlInjectionAttack, extraInfo, getSolution(), msg4);

                            sqlInjectionFoundForUrl = true;
                        }
                    }
                }
            } catch (Exception e) {

                if (this.debugEnabled)
                    log.debug("The parameter value [" + TestSQLInjection.getURLDecode(origParamValue)
                            + "] is NOT of type Integer");
                //TODO: implement a similar check for string types?  This probably need to be RDBMS specific (ie, it should not live in this scanner)
            }
        }

        //Check 2: boolean based checks.
        //the check goes like so:
        // append " and 1 = 1" to the param.  Send the query.  Check the results. Hopefully they match the original results from the unmodified query,
        // *suggesting* (but not yet definitely) that we have successfully modified the query, (hopefully not gotten an error message),
        // and have gotten the same results back, which is what you would expect if you added the constraint " and 1 = 1" to most (but not every) SQL query.
        // So was it a fluke that we got the same results back from the modified query? Perhaps the original query returned 0 rows, so adding any number of
        // constraints would change nothing?  It is still a possibility!
        // check to see if we can change the original parameter again to *restrict* the scope of the query using an AND with an always false condition (AND_ERR)
        // (decreasing the results back to nothing), or to *broaden* the scope of the query using an OR with an always true condition (AND_OR)
        // (increasing the results).
        // If we can successfully alter the results to our requirements, by one means or another, we have found a SQL Injection vulnerability.
        //Some additional complications: assume there are 2 HTML parameters: username and password, and the SQL constructed is like so:
        // select * from username where user = "$user" and password = "$password"
        // and lets assume we successfully know the type of the user field, via SQL_OR_TRUE value '" OR "1"="1' (single quotes not part of the value)
        // we still have the problem that the actual SQL executed would look like so:
        // select * from username where user = "" OR "1"="1" and password = "whateveritis"
        // Since the password field is still taken into account (by virtue of the AND condition on the password column), and we only inject one parameter at a time,
        // we are still not in control.
        // the solution is simple: add an end-of-line comment to the field added in (in this example: the user field), so that the SQL becomes:
        // select * from username where user = "" OR "1"="1" -- and password = "whateveritis"
        // the result is that any additional constraints are commented out, and the last condition to have any effect is the one whose
        // HTTP param we are manipulating.
        // Note also that because this comment only needs to be added to the "SQL_OR_TRUE" and not to the equivalent SQL_AND_FALSE, because of the nature of the OR
        // and AND conditions in SQL.
        // Corollary: If a particular RDBMS does not offer the ability to comment out the remainder of a line, we will not attempt to comment out anything in the query
        //            and we will simply hope that the *last* constraint in the SQL query is constructed from a HTTP parameter under our control.

        if (this.debugEnabled)
            log.debug("Doing Check 2, since check 1 did not match for "
                    + getBaseMsg().getRequestHeader().getURI());

        //Since the previous checks are attempting SQL injection, and may have actually succeeded in modifying the database (ask me how I know?!)
        //then we cannot rely on the database contents being the same as when the original query was last run (could be hours ago)
        //so to work around this, simply re-run the query again now at this point.
        //Note that we are not counting this request in our max number of requests to be issued
        refreshedmessage = getNewMsg();
        sendAndReceive(refreshedmessage);

        //String mResBodyNormal = getBaseMsg().getResponseBody().toString();
        mResBodyNormalUnstripped = refreshedmessage.getResponseBody().toString();
        mResBodyNormalStripped = this.stripOff(mResBodyNormalUnstripped, origParamValue);

        //boolean booleanBasedSqlInjectionFoundForParam = false;

        //try each of the AND syntax values in turn.
        //Which one is successful will depend on the column type of the table/view column into which we are injecting the SQL.
        for (int i = 0; i < SQL_LOGIC_AND_TRUE.length && !sqlInjectionFoundForUrl && doBooleanBased
                && countBooleanBasedRequests < doBooleanMaxRequests; i++) {
            //needs a new message for each type of AND to be issued
            HttpMessage msg2 = getNewMsg();
            String sqlBooleanAndTrueValue = TestSQLInjection.getURLDecode(origParamValue)
                    + SQL_LOGIC_AND_TRUE[i];
            String sqlBooleanAndFalseValue = TestSQLInjection.getURLDecode(origParamValue)
                    + SQL_LOGIC_AND_FALSE[i];

            setParameter(msg2, param, sqlBooleanAndTrueValue);

            //send the AND with an additional TRUE statement tacked onto the end. Hopefully it will return the same results as the original (to find a vulnerability)
            sendAndReceive(msg2);
            countBooleanBasedRequests++;

            //String resBodyAND = msg2.getResponseBody().toString();
            String resBodyANDTrueUnstripped = msg2.getResponseBody().toString();
            String resBodyANDTrueStripped = this.stripOff(resBodyANDTrueUnstripped, sqlBooleanAndTrueValue);

            //set up two little arrays to ease the work of checking the unstripped output, and then the stripped output
            String normalBodyOutput[] = { mResBodyNormalUnstripped, mResBodyNormalStripped };
            String andTrueBodyOutput[] = { resBodyANDTrueUnstripped, resBodyANDTrueStripped };
            boolean strippedOutput[] = { false, true };

            for (int booleanStrippedUnstrippedIndex = 0; booleanStrippedUnstrippedIndex < 2; booleanStrippedUnstrippedIndex++) {
                //if the results of the "AND 1=1" match the original query (using either the stipped or unstripped versions), we may be onto something.
                if (andTrueBodyOutput[booleanStrippedUnstrippedIndex]
                        .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) == 0) {
                    if (this.debugEnabled)
                        log.debug("Check 2, "
                                + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for AND TRUE condition [" + sqlBooleanAndTrueValue
                                + "] matched (refreshed) original results for "
                                + refreshedmessage.getRequestHeader().getURI());
                    //so they match. Was it a fluke? See if we get the same result by tacking on "AND 1 = 2" to the original
                    HttpMessage msg2_and_false = getNewMsg();

                    setParameter(msg2_and_false, param, sqlBooleanAndFalseValue);

                    sendAndReceive(msg2_and_false);
                    countBooleanBasedRequests++;

                    //String resBodyANDFalse = stripOff(msg2_and_false.getResponseBody().toString(), SQL_LOGIC_AND_FALSE[i]);
                    //String resBodyANDFalse = msg2_and_false.getResponseBody().toString();
                    String resBodyANDFalseUnstripped = msg2_and_false.getResponseBody().toString();
                    String resBodyANDFalseStripped = this.stripOff(resBodyANDFalseUnstripped,
                            sqlBooleanAndFalseValue);

                    String andFalseBodyOutput[] = { resBodyANDFalseUnstripped, resBodyANDFalseStripped };

                    //which AND False output should we compare? the stripped or the unstripped version?
                    //depends on which one we used to get to here.. use the same as that..

                    // build an always false AND query.  Result should be different to prove the SQL works.
                    if (andFalseBodyOutput[booleanStrippedUnstrippedIndex]
                            .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) {
                        if (this.debugEnabled)
                            log.debug("Check 2, "
                                    + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                            : "UNSTRIPPED")
                                    + " html output for AND FALSE condition [" + sqlBooleanAndFalseValue
                                    + "] differed from (refreshed) original results for "
                                    + refreshedmessage.getRequestHeader().getURI());

                        //it's different (suggesting that the "AND 1 = 2" appended on gave different results because it restricted the data set to nothing
                        //Likely a SQL Injection. Raise it
                        String extraInfo = null;
                        if (strippedOutput[booleanStrippedUnstrippedIndex])
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                    sqlBooleanAndTrueValue, sqlBooleanAndFalseValue, "");
                        else
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                    sqlBooleanAndTrueValue, sqlBooleanAndFalseValue, "NOT ");
                        extraInfo = extraInfo + "\n" + Constant.messages
                                .getString("ascanrules.sqlinjection.alert.booleanbased.extrainfo.dataexists");

                        //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                        sqlInjectionAttack = sqlBooleanAndTrueValue;
                        bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                param, sqlInjectionAttack, extraInfo, getSolution(), msg2);

                        sqlInjectionFoundForUrl = true;

                        continue; //to the next entry in SQL_AND
                    } else {
                        //the results of the always false condition are the same as for the original unmodified parameter
                        //this could be because there was *no* data returned for the original unmodified parameter
                        //so consider the effect of adding comments to both the always true condition, and the always false condition
                        //the first value to try..
                        String orValue = TestSQLInjection.getURLDecode(origParamValue) + SQL_LOGIC_OR_TRUE[i];

                        //this is where that comment comes in handy: if the RDBMS supports one-line comments, add one in to attempt to ensure that the
                        //condition becomes one that is effectively always true, returning ALL data (or as much as possible), allowing us to pinpoint the SQL Injection
                        if (this.debugEnabled)
                            log.debug("Check 2 , "
                                    + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                            : "UNSTRIPPED")
                                    + " html output for AND FALSE condition [" + sqlBooleanAndFalseValue
                                    + "] SAME as (refreshed) original results for "
                                    + refreshedmessage.getRequestHeader().getURI()
                                    + " ### (forcing OR TRUE check) ");
                        HttpMessage msg2_or_true = getNewMsg();
                        setParameter(msg2_or_true, param, orValue);
                        sendAndReceive(msg2_or_true);
                        countBooleanBasedRequests++;

                        //String resBodyORTrue = stripOff(msg2_or_true.getResponseBody().toString(), orValue);
                        //String resBodyORTrue = msg2_or_true.getResponseBody().toString();
                        String resBodyORTrueUnstripped = msg2_or_true.getResponseBody().toString();
                        String resBodyORTrueStripped = this.stripOff(resBodyORTrueUnstripped, orValue);

                        String orTrueBodyOutput[] = { resBodyORTrueUnstripped, resBodyORTrueStripped };

                        int compareOrToOriginal = orTrueBodyOutput[booleanStrippedUnstrippedIndex]
                                .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]);
                        if (compareOrToOriginal != 0) {

                            if (this.debugEnabled)
                                log.debug("Check 2, "
                                        + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                                : "UNSTRIPPED")
                                        + " html output for OR TRUE condition [" + orValue
                                        + "] different to (refreshed) original results for "
                                        + refreshedmessage.getRequestHeader().getURI());

                            //it's different (suggesting that the "OR 1 = 1" appended on gave different results because it broadened the data set from nothing to something
                            //Likely a SQL Injection. Raise it
                            String extraInfo = null;
                            if (strippedOutput[booleanStrippedUnstrippedIndex])
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                        sqlBooleanAndTrueValue, orValue, "");
                            else
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                        sqlBooleanAndTrueValue, orValue, "NOT ");
                            extraInfo = extraInfo + "\n" + Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.booleanbased.extrainfo.datanotexists");

                            //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                            sqlInjectionAttack = orValue;
                            bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                    param, sqlInjectionAttack, extraInfo, getSolution(), msg2);

                            sqlInjectionFoundForUrl = true;
                            //booleanBasedSqlInjectionFoundForParam = true;  //causes us to skip past the other entries in SQL_AND.  Only one will expose a vuln for a given param, since the database column is of only 1 type

                            continue;
                        }
                    }
                } //if the results of the "AND 1=1" match the original query, we may be onto something.
                else {
                    //andTrueBodyOutput[booleanStrippedUnstrippedIndex].compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex])
                    //the results of the "AND 1=1" do NOT match the original query, for whatever reason (no sql injection, or the web page is not stable)
                    if (this.debugEnabled) {
                        log.debug("Check 2, "
                                + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for AND condition [" + sqlBooleanAndTrueValue
                                + "] does NOT match the (refreshed) original results for "
                                + refreshedmessage.getRequestHeader().getURI());
                        Patch diffpatch = DiffUtils.diff(
                                new LinkedList<String>(Arrays
                                        .asList(normalBodyOutput[booleanStrippedUnstrippedIndex].split("\\n"))),
                                new LinkedList<String>(Arrays.asList(
                                        andTrueBodyOutput[booleanStrippedUnstrippedIndex].split("\\n"))));

                        //int numberofDifferences = diffpatch.getDeltas().size();

                        //and convert the list of patches to a String, joining using a newline
                        StringBuilder tempDiff = new StringBuilder(250);
                        for (Delta delta : diffpatch.getDeltas()) {
                            String changeType = null;
                            if (delta.getType() == Delta.TYPE.CHANGE)
                                changeType = "Changed Text";
                            else if (delta.getType() == Delta.TYPE.DELETE)
                                changeType = "Deleted Text";
                            else if (delta.getType() == Delta.TYPE.INSERT)
                                changeType = "Inserted text";
                            else
                                changeType = "Unknown change type [" + delta.getType() + "]";

                            tempDiff.append("\n(" + changeType + ")\n"); //blank line before
                            tempDiff.append("Output for Unmodified parameter: " + delta.getOriginal() + "\n");
                            tempDiff.append("Output for   modified parameter: " + delta.getRevised() + "\n");
                        }
                        log.debug("DIFFS: " + tempDiff);
                    }
                }

            } //end of boolean logic output index (unstripped + stripped)
        }
        //end of check 2

        //Check 3: UNION based
        //for each SQL UNION combination to try
        for (int sqlUnionStringIndex = 0; sqlUnionStringIndex < SQL_UNION_APPENDAGES.length
                && !sqlInjectionFoundForUrl && doUnionBased
                && countUnionBasedRequests < doUnionMaxRequests; sqlUnionStringIndex++) {

            //new message for each value we attack with
            HttpMessage msg3 = getNewMsg();
            String sqlUnionValue = origParamValue + SQL_UNION_APPENDAGES[sqlUnionStringIndex];
            setParameter(msg3, param, sqlUnionValue);
            //send the message with the modified parameters
            sendAndReceive(msg3);
            countUnionBasedRequests++;

            //now check the results.. look first for UNION specific error messages in the output that were not there in the original output
            //and failing that, look for generic RDBMS specific error messages
            //TODO: maybe also try looking at a differentiation based approach?? Prone to false positives though.
            Iterator<String> errorPatternUnionIterator = SQL_UNION_ERROR_TO_DBMS.keySet().iterator();

            while (errorPatternUnionIterator.hasNext() && !sqlInjectionFoundForUrl) {
                String errorPatternKey = errorPatternUnionIterator.next();
                String errorPatternRDBMS = SQL_UNION_ERROR_TO_DBMS.get(errorPatternKey);

                //Note: must escape the strings, in case they contain strings like "[Microsoft], which would be interpreted as regular character class regexps"
                Pattern errorPattern = Pattern.compile("\\Q" + errorPatternKey + "\\E", PATTERN_PARAM);

                //if the "error message" occurs in the result of sending the modified query, but did NOT occur in the original result of the original query
                //then we may may have a SQL Injection vulnerability
                StringBuilder sb = new StringBuilder();
                String sqlUnionBodyUnstripped = msg3.getResponseBody().toString();
                String sqlUnionBodyStripped = this.stripOff(sqlUnionBodyUnstripped, sqlUnionValue);

                Matcher matcherOrig = errorPattern.matcher(mResBodyNormalStripped);
                Matcher matcherSQLUnion = errorPattern.matcher(sqlUnionBodyStripped);
                boolean patternInOrig = matcherOrig.find();
                boolean patternInSQLUnion = matcherSQLUnion.find();

                //if (! matchBodyPattern(getBaseMsg(), errorPattern, null) && matchBodyPattern(msg3, errorPattern, sb)) {
                if (!patternInOrig && patternInSQLUnion) {
                    //Likely a UNION Based SQL Injection (by error message). Raise it
                    String extraInfo = Constant.messages.getString(
                            "ascanrules.sqlinjection.alert.unionbased.extrainfo", errorPatternRDBMS,
                            errorPatternKey);

                    //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                    sqlInjectionAttack = sqlUnionValue;
                    bingo(Alert.RISK_HIGH, Alert.WARNING, getName() + " - " + errorPatternRDBMS,
                            getDescription(), refreshedmessage.getRequestHeader().getURI().getURI(), //url
                            param, sqlInjectionAttack, extraInfo, getSolution(), msg3);

                    //log it, as the RDBMS may be useful to know later (in subsequent checks, when we need to determine RDBMS specific behaviour, for instance)
                    getKb().add(refreshedmessage.getRequestHeader().getURI(), "sql/" + errorPatternRDBMS,
                            Boolean.TRUE);

                    sqlInjectionFoundForUrl = true;
                    continue;
                }
            } //end of the loop to check for RDBMS specific UNION error messages
        } ////for each SQL UNION combination to try
          //end of check 3

        //###############################

        //check for columns used in the "order by" clause of a SQL statement. earlier tests will likely not catch these

        //append on " ASC -- " to the end of the original parameter. Grab the results.
        //if the results are different to the original (unmodified parameter) results, then bale
        //if the results are the same as for the original parameter value, then the parameter *might* be influencing the order by
        //   try again for "DESC": append on " DESC -- " to the end of the original parameter. Grab the results.
        //   if the results are the same as the original (unmodified parameter) results, then bale
        //   (the results are not under our control, or there is no difference in the ordering, for some reason: 0 or 1 rows only, or ordering
        //   by the first column alone is not sufficient to change the ordering of the data.)
        //   if the results were different to the original (unmodified parameter) results, then
        //      SQL injection!!

        //Since the previous checks are attempting SQL injection, and may have actually succeeded in modifying the database (ask me how I know?!)
        //then we cannot rely on the database contents being the same as when the original query was last run (could be hours ago)
        //so to work around this, simply re-run the query again now at this point.
        //Note that we are not counting this request in our max number of requests to be issued
        refreshedmessage = getNewMsg();
        sendAndReceive(refreshedmessage);

        //String mResBodyNormal = getBaseMsg().getResponseBody().toString();
        mResBodyNormalUnstripped = refreshedmessage.getResponseBody().toString();
        mResBodyNormalStripped = this.stripOff(mResBodyNormalUnstripped, origParamValue);

        if (!sqlInjectionFoundForUrl && doOrderByBased && countOrderByBasedRequests < doOrderByMaxRequests) {

            String modifiedParamValue = TestSQLInjection.getURLDecode(origParamValue) + " ASC "
                    + SQL_ONE_LINE_COMMENT;

            HttpMessage msg5 = getNewMsg();
            setParameter(msg5, param, modifiedParamValue);

            sendAndReceive(msg5);
            countOrderByBasedRequests++;

            String modifiedAscendingOutputUnstripped = msg5.getResponseBody().toString();
            String modifiedAscendingOutputStripped = this.stripOff(modifiedAscendingOutputUnstripped,
                    modifiedParamValue);

            //set up two little arrays to ease the work of checking the unstripped output, and then the stripped output
            String normalBodyOutput[] = { mResBodyNormalUnstripped, mResBodyNormalStripped };
            String ascendingBodyOutput[] = { modifiedAscendingOutputUnstripped,
                    modifiedAscendingOutputStripped };
            boolean strippedOutput[] = { false, true };

            for (int booleanStrippedUnstrippedIndex = 0; booleanStrippedUnstrippedIndex < 2; booleanStrippedUnstrippedIndex++) {
                //if the results of the modified request match the original query, we may be onto something.
                if (ascendingBodyOutput[booleanStrippedUnstrippedIndex]
                        .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) == 0) {
                    if (this.debugEnabled)
                        log.debug("Check X, "
                                + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for modified Order By parameter [" + modifiedParamValue
                                + "] matched (refreshed) original results for "
                                + refreshedmessage.getRequestHeader().getURI());
                    //confirm that a different parameter value generates different output, to minimise false positives

                    //use the descending order this time
                    String modifiedParamValueConfirm = TestSQLInjection.getURLDecode(origParamValue) + " DESC "
                            + SQL_ONE_LINE_COMMENT;

                    HttpMessage msg5Confirm = getNewMsg();
                    setParameter(msg5Confirm, param, modifiedParamValueConfirm);

                    sendAndReceive(msg5Confirm);
                    countOrderByBasedRequests++;

                    String confirmOrderByOutputUnstripped = msg5Confirm.getResponseBody().toString();
                    String confirmOrderByOutputStripped = this.stripOff(confirmOrderByOutputUnstripped,
                            modifiedParamValueConfirm);

                    //set up two little arrays to ease the work of checking the unstripped output or the stripped output
                    String confirmOrderByBodyOutput[] = { confirmOrderByOutputUnstripped,
                            confirmOrderByOutputStripped };

                    if (confirmOrderByBodyOutput[booleanStrippedUnstrippedIndex]
                            .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) {
                        //the confirm query did not return the same results.  This means that arbitrary queries are not all producing the same page output.
                        //this means the fact we earlier reproduced the original page output with a modified parameter was not a coincidence

                        //Likely a SQL Injection. Raise it
                        String extraInfo = null;
                        if (strippedOutput[booleanStrippedUnstrippedIndex])
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.orderbybased.extrainfo", modifiedParamValue,
                                    "");
                        else
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.orderbybased.extrainfo", modifiedParamValue,
                                    "NOT ");

                        //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                        sqlInjectionAttack = modifiedParamValue;
                        bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                param, sqlInjectionAttack, extraInfo, getSolution(), msg5);

                        sqlInjectionFoundForUrl = true;
                    }
                }
            }

        }

        //###############################

        //if a sql injection was found, we should check if the page is flagged as a login page
        //in any of the contexts.  if it is, raise an "SQL Injection - Authentication Bypass" alert in addition to the alerts already raised
        if (sqlInjectionFoundForUrl) {
            boolean loginUrl = false;
            //log.debug("### A SQL Injection may lead to auth bypass..");

            //are we dealing with a login url in any of the contexts?
            ExtensionAuth extAuth = (ExtensionAuth) Control.getSingleton().getExtensionLoader()
                    .getExtension(ExtensionAuth.NAME);
            URI requestUri = getBaseMsg().getRequestHeader().getURI();

            //using the session, get the list of contexts for the url
            List<Context> contextList = extAuth.getModel().getSession().getContextsForUrl(requestUri.getURI());

            //now loop, and see if the url is a login url in each of the contexts in turn..
            for (Context context : contextList) {
                HttpMessage loginRequest = extAuth.getApi().getLoginRequest(context.getIndex());
                if (loginRequest != null) {
                    URI loginUri = loginRequest.getRequestHeader().getURI();
                    if (requestUri.getScheme().equals(loginUri.getScheme())
                            && requestUri.getHost().equals(loginUri.getHost())
                            && requestUri.getPort() == loginUri.getPort()
                            && requestUri.getPath().equals(loginUri.getPath())) {
                        //we got this far.. only the method (GET/POST), user details, query params, fragment, and POST params
                        //are possibly different from the login page.
                        loginUrl = true;
                        //DEBUG only
                        //log.debug("##### The right login page was found");
                        break;
                    } else {
                        //log.debug("#### This is not the login page you're looking for");
                    }
                } else {
                    //log.debug("### This context has no login page set");
                }
            }
            if (loginUrl) {
                //log.debug("##### Raising auth bypass");
                //raise the alert, using the custom name and description
                String vulnname = Constant.messages.getString("ascanrules.sqlinjection.authbypass.name");
                String vulndesc = Constant.messages.getString("ascanrules.sqlinjection.authbypass.desc");

                //raise the alert, using the attack string stored earlier for this purpose
                bingo(Alert.RISK_HIGH, Alert.WARNING, vulnname, vulndesc,
                        refreshedmessage.getRequestHeader().getURI().getURI(), //url
                        param, sqlInjectionAttack, "", getSolution(), getBaseMsg());

            } //not a login page
        } //no sql Injection Found For Url

    } catch (Exception e) {
        //Do not try to internationalise this.. we need an error message in any event..
        //if it's in English, it's still better than not having it at all.
        log.error("An error occurred checking a url for SQL Injection vulnerabilities", e);
    }
}