Example usage for java.net SocketException getMessage

List of usage examples for java.net SocketException getMessage

Introduction

In this page you can find the example usage for java.net SocketException getMessage.

Prototype

public String getMessage() 

Source Link

Document

Returns the detail message string of this throwable.

Usage

From source file:org.zaproxy.zap.extension.ascanrules.TestSQLInjection.java

/** scans for SQL Injection vulnerabilities */
@Override/* w  w  w  . j  a  v  a 2 s  . c om*/
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.
    // reinitialise each parameter.
    sqlInjectionFoundForUrl = false;
    sqlInjectionAttack = null;
    refreshedmessage = null;
    mResBodyNormalUnstripped = null;
    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
        countErrorBasedRequests = 0;
        countExpressionBasedRequests = 0;
        countBooleanBasedRequests = 0;
        countUnionBasedRequests = 0;
        countOrderByBasedRequests = 0;

        // 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
                && doSpecificErrorBased
                && 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) {
                // ZAP: Removed getURLDecode()
                prefixStrings = new String[] { "", origParamValue };
            } else {
                prefixStrings = new String[] { "" };
            }
            for (int prefixIndex = 0; prefixIndex < prefixStrings.length
                    && !sqlInjectionFoundForUrl; 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
                try {
                    sendAndReceive(msg1, false); // do not follow redirects
                } catch (SocketException ex) {
                    if (log.isDebugEnabled())
                        log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage()
                                + " when accessing: " + msg1.getRequestHeader().getURI().toString());
                    continue; // Something went wrong, continue to the next prefixString in the
                    // loop
                }
                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.
                for (RDBMS rdbms : RDBMS.values()) {
                    if (getTechSet().includes(rdbms.getTech())
                            && checkSpecificErrors(rdbms, msg1, param, sqlErrValue)) {
                        sqlInjectionFoundForUrl = true;
                        // Save the attack string for the "Authentication Bypass" alert, if
                        // necessary
                        sqlInjectionAttack = sqlErrValue;
                        break;
                    }
                    // bale out if we were asked nicely
                    if (isStop()) {
                        log.debug("Stopping the scan due to a user request");
                        return;
                    }
                } // end of the loop to check for RDBMS specific error messages

                if (this.doGenericErrorBased && !sqlInjectionFoundForUrl) {
                    Iterator<Pattern> errorPatternIterator = RDBMS.GenericRDBMS.getErrorPatterns().iterator();

                    while (errorPatternIterator.hasNext() && !sqlInjectionFoundForUrl) {
                        Pattern errorPattern = errorPatternIterator.next();
                        String errorPatternRDBMS = RDBMS.GenericRDBMS.getName();

                        // 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(
                                    MESSAGE_PREFIX + "alert.errorbased.extrainfo", errorPatternRDBMS,
                                    errorPattern.toString());
                            // raise the alert, and save the attack string for the
                            // "Authentication Bypass" alert, if necessary
                            sqlInjectionAttack = sqlErrValue;
                            bingo(Alert.RISK_HIGH, Alert.CONFIDENCE_MEDIUM,
                                    getName() + " - " + errorPatternRDBMS, getDescription(), null, param,
                                    sqlInjectionAttack, extraInfo, getSolution(), sb.toString(), 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;
                        }
                        // bale out if we were asked nicely
                        if (isStop()) {
                            log.debug("Stopping the scan due to a user request");
                            return;
                        }
                    } // 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();
        try {
            sendAndReceive(refreshedmessage, false); // do not follow redirects
        } catch (SocketException ex) {
            if (log.isDebugEnabled())
                log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                        + refreshedmessage.getRequestHeader().getURI().toString());
            return; // Something went wrong, no point continuing
        }

        // 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?
                // ZAP: removed URLDecoding because on Variants
                // int paramAsInt =
                // Integer.parseInt(TestSQLInjection.getURLDecode(origParamValue));
                int paramAsInt = Integer.parseInt(origParamValue);

                if (this.debugEnabled) {
                    log.debug("The parameter value [" + origParamValue + "] is of type Integer");
                }
                // This check is implemented using two variant PLUS(+) and MULT(*)
                try {
                    // PLUS variant check the param value "3-2" gives same result as original
                    // request and param value "4-2" gives different result if original param
                    // value is 1
                    // set the parameter value to a string value like "3-2", if the original
                    // parameter value was "1"
                    int paramPlusTwo = addWithOverflowCheck(paramAsInt, 2);
                    String modifiedParamValueForAdd = String.valueOf(paramPlusTwo) + "-2";
                    // set the parameter value to a string value like "4-2", if the original
                    // parameter value was "1"
                    int paramPlusThree = addWithOverflowCheck(paramAsInt, 3);
                    String modifiedParamValueConfirmForAdd = String.valueOf(paramPlusThree) + "-2";
                    // Do the attack for ADD variant
                    expressionBasedAttack(param, origParamValue, modifiedParamValueForAdd,
                            modifiedParamValueConfirmForAdd);
                    // bale out if we were asked nicely
                    if (isStop()) {
                        log.debug("Stopping the scan due to a user request");
                        return;
                    }
                    // MULT variant check the param value "2/2" gives same result as original
                    // request and param value "4/2" gives different result if original param
                    // value is 1
                    if (!sqlInjectionFoundForUrl && countExpressionBasedRequests < doExpressionMaxRequests) {
                        // set the parameter value to a string value like "2/2", if the original
                        // parameter value was "1"
                        int paramMultTwo = multiplyWithOverflowCheck(paramAsInt, 2);
                        String modifiedParamValueForMult = String.valueOf(paramMultTwo) + "/2";
                        // set the parameter value to a string value like "4/2", if the original
                        // parameter value was "1"
                        int paramMultFour = multiplyWithOverflowCheck(paramAsInt, 4);
                        String modifiedParamValueConfirmForMult = String.valueOf(paramMultFour) + "/2";
                        // Do the attack for MULT variant
                        expressionBasedAttack(param, origParamValue, modifiedParamValueForMult,
                                modifiedParamValueConfirmForMult);
                        // bale out if we were asked nicely
                        if (isStop()) {
                            log.debug("Stopping the scan due to a user request");
                            return;
                        }
                    }
                } catch (ArithmeticException ex) {
                    if (this.debugEnabled) {
                        log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage()
                                + "When performing integer math with the parameter value [" + origParamValue
                                + "]");
                    }
                }
            } catch (Exception e) {
                if (this.debugEnabled) {
                    log.debug("The parameter value [" + origParamValue + "] is NOT of type Integer");
                }
                // TODO: implement a similar check for string types?  This probably needs 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();
        try {
            sendAndReceive(refreshedmessage, false); // do not follow redirects
        } catch (SocketException ex) {
            if (log.isDebugEnabled())
                log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                        + refreshedmessage.getRequestHeader().getURI().toString());
            return; // Something went wrong, no point continuing
        }

        // 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();
            // ZAP: Removed getURLDecode()
            String sqlBooleanAndTrueValue = origParamValue + SQL_LOGIC_AND_TRUE[i];
            String sqlBooleanAndFalseValue = 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)
            try {
                sendAndReceive(msg2, false); // do not follow redirects
            } catch (SocketException ex) {
                if (log.isDebugEnabled())
                    log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                            + msg2.getRequestHeader().getURI().toString());
                continue; // Something went wrong, continue to the next item in the loop
            }
            countBooleanBasedRequests++;

            // String resBodyAND = msg2.getResponseBody().toString();
            String resBodyANDTrueUnstripped = msg2.getResponseBody().toString();
            String resBodyANDTrueStripped = stripOffOriginalAndAttackParam(resBodyANDTrueUnstripped,
                    origParamValue, 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);

                    try {
                        sendAndReceive(msg2_and_false, false); // do not follow redirects
                    } catch (SocketException ex) {
                        if (log.isDebugEnabled())
                            log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage()
                                    + " when accessing: "
                                    + msg2_and_false.getRequestHeader().getURI().toString());
                        continue; // Something went wrong, continue on to the next item in the
                        // loop
                    }
                    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 = stripOffOriginalAndAttackParam(resBodyANDFalseUnstripped,
                            origParamValue, 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(
                                    MESSAGE_PREFIX + "alert.booleanbased.extrainfo", sqlBooleanAndTrueValue,
                                    sqlBooleanAndFalseValue, "");
                        } else {
                            extraInfo = Constant.messages.getString(
                                    MESSAGE_PREFIX + "alert.booleanbased.extrainfo", sqlBooleanAndTrueValue,
                                    sqlBooleanAndFalseValue, "NOT ");
                        }
                        extraInfo = extraInfo + "\n" + Constant.messages
                                .getString(MESSAGE_PREFIX + "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.CONFIDENCE_MEDIUM, getName(), getDescription(), null, // url
                                param, sqlInjectionAttack, extraInfo, getSolution(), "", msg2);

                        sqlInjectionFoundForUrl = true;

                        break; // No further need to loop through 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..
                        // ZAP: Removed getURLDecode()
                        String orValue = 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);
                        try {
                            sendAndReceive(msg2_or_true, false); // do not follow redirects
                        } catch (SocketException ex) {
                            if (log.isDebugEnabled())
                                log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage()
                                        + " when accessing: "
                                        + msg2_or_true.getRequestHeader().getURI().toString());
                            continue; // Something went wrong, continue on to the next item in
                            // the loop
                        }
                        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 = stripOffOriginalAndAttackParam(resBodyORTrueUnstripped,
                                origParamValue, 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(
                                        MESSAGE_PREFIX + "alert.booleanbased.extrainfo", sqlBooleanAndTrueValue,
                                        orValue, "");
                            } else {
                                extraInfo = Constant.messages.getString(
                                        MESSAGE_PREFIX + "alert.booleanbased.extrainfo", sqlBooleanAndTrueValue,
                                        orValue, "NOT ");
                            }
                            extraInfo = extraInfo + "\n" + Constant.messages
                                    .getString(MESSAGE_PREFIX + "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.CONFIDENCE_MEDIUM, 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

                            break; // No further need to loop
                        }
                    }
                } // 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);
                    }
                }
                // bale out if we were asked nicely
                if (isStop()) {
                    log.debug("Stopping the scan due to a user request");
                    return;
                }
            } // end of boolean logic output index (unstripped + stripped)
        }
        // end of check 2

        // check 2a: boolean based logic, where the original query returned *no* data. Here we
        // append " OR 1=1" in an attempt to extract *more* data
        // and then verify the results by attempting to reproduce the original results by
        // appending an " AND 1=2" condition (ie "open up first, then restrict to verify")
        // this differs from the previous logic based check since the previous check assumes
        // that the original query produced data, and tries first to restrict that data
        // (ie, it uses "restrict first, open up to verify" ).
        for (int i = 0; i < SQL_LOGIC_OR_TRUE.length && !sqlInjectionFoundForUrl && doBooleanBased
                && countBooleanBasedRequests < doBooleanMaxRequests; i++) {
            HttpMessage msg2 = getNewMsg();
            String sqlBooleanOrTrueValue = origParamValue + SQL_LOGIC_OR_TRUE[i];
            String sqlBooleanAndFalseValue = origParamValue + SQL_LOGIC_AND_FALSE[i];

            setParameter(msg2, param, sqlBooleanOrTrueValue);
            try {
                sendAndReceive(msg2, false); // do not follow redirects
            } catch (SocketException ex) {
                if (log.isDebugEnabled())
                    log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                            + msg2.getRequestHeader().getURI().toString());
                continue; // Something went wrong, continue on to the next item in the loop
            }
            countBooleanBasedRequests++;

            String resBodyORTrueUnstripped = msg2.getResponseBody().toString();

            // if the results of the "OR 1=1" exceed the original query (unstripped, by more
            // than a 20% size difference, say), we may be onto something.
            // TODO: change the percentage difference threshold based on the alert threshold
            if ((resBodyORTrueUnstripped.length() > (mResBodyNormalUnstripped.length() * 1.2))) {
                if (this.debugEnabled) {
                    log.debug("Check 2a, unstripped html output for OR TRUE condition [" + sqlBooleanOrTrueValue
                            + "] produced sufficiently larger results than the original message");
                }
                // if we can also restrict it back to the original results by appending a " and
                // 1=2", then "Winner Winner, Chicken Dinner".
                HttpMessage msg2_and_false = getNewMsg();
                setParameter(msg2_and_false, param, sqlBooleanAndFalseValue);
                try {
                    sendAndReceive(msg2_and_false, false); // do not follow redirects
                } catch (SocketException ex) {
                    if (log.isDebugEnabled())
                        log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage()
                                + " when accessing: " + msg2_and_false.getRequestHeader().getURI().toString());
                    continue; // Something went wrong, continue on to the next item in the loop
                }
                countBooleanBasedRequests++;

                String resBodyANDFalseUnstripped = msg2_and_false.getResponseBody().toString();
                String resBodyANDFalseStripped = stripOffOriginalAndAttackParam(resBodyANDFalseUnstripped,
                        origParamValue, sqlBooleanAndFalseValue);

                // does the "AND 1=2" version produce the same as the original (for
                // stripped/unstripped versions)
                boolean verificationUsingUnstripped = resBodyANDFalseUnstripped
                        .compareTo(mResBodyNormalUnstripped) == 0;
                boolean verificationUsingStripped = resBodyANDFalseStripped
                        .compareTo(mResBodyNormalStripped) == 0;
                if (verificationUsingUnstripped || verificationUsingStripped) {
                    if (this.debugEnabled) {
                        log.debug("Check 2, " + (verificationUsingStripped ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for AND FALSE condition [" + sqlBooleanAndFalseValue
                                + "] matches the (refreshed) original results");
                    }
                    // Likely a SQL Injection. Raise it
                    String extraInfo = null;
                    if (verificationUsingStripped) {
                        extraInfo = Constant.messages.getString(MESSAGE_PREFIX + "alert.booleanbased.extrainfo",
                                sqlBooleanOrTrueValue, sqlBooleanAndFalseValue, "");
                    } else {
                        extraInfo = Constant.messages.getString(MESSAGE_PREFIX + "alert.booleanbased.extrainfo",
                                sqlBooleanOrTrueValue, sqlBooleanAndFalseValue, "NOT ");
                    }
                    extraInfo = extraInfo + "\n" + Constant.messages
                            .getString(MESSAGE_PREFIX + "alert.booleanbased.extrainfo.datanotexists");

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

                    sqlInjectionFoundForUrl = true;

                    break; // No further need to loop
                }
            }
        }
        // end of check 2a

        // 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
            try {
                sendAndReceive(msg3, false); // do not follow redirects
            } catch (SocketException ex) {
                if (log.isDebugEnabled())
                    log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                            + msg3.getRequestHeader().getURI().toString());
                continue; // Something went wrong, continue on to the next item in the loop
            }
            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.
            for (RDBMS rdbms : RDBMS.values()) {
                if (getTechSet().includes(rdbms.getTech()) && checkUnionErrors(rdbms, msg3,
                        mResBodyNormalStripped, refreshedmessage.getRequestHeader().getURI(), param,
                        origParamValue, sqlUnionValue)) {
                    sqlInjectionFoundForUrl = true;
                    // Save the attack string for the "Authentication Bypass" alert, if
                    // necessary
                    sqlInjectionAttack = sqlUnionValue;
                    break;
                }
                // bale out if we were asked nicely
                if (isStop()) {
                    log.debug("Stopping the scan due to a user request");
                    return;
                }
            } // 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();
        try {
            sendAndReceive(refreshedmessage, false); // do not follow redirects
        } catch (SocketException ex) {
            if (log.isDebugEnabled())
                log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                        + refreshedmessage.getRequestHeader().getURI().toString());
            return; // Something went wrong, no point continuing
        }

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

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

            // ZAP: Removed getURLDecode()
            String modifiedParamValue = origParamValue + " ASC " + SQL_ONE_LINE_COMMENT;

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

            try {
                sendAndReceive(msg5, false); // do not follow redirects
            } catch (SocketException ex) {
                if (log.isDebugEnabled())
                    log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                            + msg5.getRequestHeader().getURI().toString());
                return; // Something went wrong, no point continuing
            }
            countOrderByBasedRequests++;

            String modifiedAscendingOutputUnstripped = msg5.getResponseBody().toString();
            String modifiedAscendingOutputStripped = stripOffOriginalAndAttackParam(
                    modifiedAscendingOutputUnstripped, origParamValue, 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
                    // ZAP: Removed getURLDecode()
                    String modifiedParamValueConfirm = origParamValue + " DESC " + SQL_ONE_LINE_COMMENT;

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

                    try {
                        sendAndReceive(msg5Confirm, false); // do not follow redirects
                    } catch (SocketException ex) {
                        if (log.isDebugEnabled())
                            log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage()
                                    + " when accessing: " + msg5Confirm.getRequestHeader().getURI().toString());
                        continue; // Something went wrong, continue on to the next item in the
                        // loop
                    }
                    countOrderByBasedRequests++;

                    String confirmOrderByOutputUnstripped = msg5Confirm.getResponseBody().toString();
                    String confirmOrderByOutputStripped = stripOffOriginalAndAttackParam(
                            confirmOrderByOutputUnstripped, origParamValue, 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(
                                    MESSAGE_PREFIX + "alert.orderbybased.extrainfo", modifiedParamValue, "");
                        } else {
                            extraInfo = Constant.messages.getString(
                                    MESSAGE_PREFIX + "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.CONFIDENCE_MEDIUM, getName(), getDescription(), null, // url
                                param, sqlInjectionAttack, extraInfo, getSolution(), "", msg5);

                        sqlInjectionFoundForUrl = true;
                        break; // No further need to loop
                    }
                }
                // bale out if we were asked nicely
                if (isStop()) {
                    log.debug("Stopping the scan due to a user request");
                    return;
                }
            }
        }

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

        // 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?
            ExtensionAuthentication extAuth = (ExtensionAuthentication) Control.getSingleton()
                    .getExtensionLoader().getExtension(ExtensionAuthentication.NAME);
            if (extAuth != null) {
                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) {
                    URI loginUri = extAuth.getLoginRequestURIForContext(context);
                    if (loginUri != null) {
                        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(MESSAGE_PREFIX + "authbypass.name");
                String vulndesc = Constant.messages.getString(MESSAGE_PREFIX + "authbypass.desc");

                // raise the alert, using the attack string stored earlier for this purpose
                bingo(Alert.RISK_HIGH, Alert.CONFIDENCE_MEDIUM, vulnname, vulndesc,
                        refreshedmessage.getRequestHeader().getURI().getURI(), // url
                        param, sqlInjectionAttack, "", getSolution(), "", getBaseMsg());
            } // not a login page
        } // no sql Injection Found For Url

    } catch (InvalidRedirectLocationException e) {
        // Not an error, just means we probably attacked the redirect location
    } 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);
    }
}

From source file:net.pms.network.UPNPHelper.java

/**
 * Starts up two threads: one to broadcast UPnP ALIVE messages and another
 * to listen for responses. /*ww w  .j av  a  2s. c o m*/
 *
 * @throws IOException Signals that an I/O exception has occurred.
 */
public static void listen() throws IOException {
    Runnable rAlive = new Runnable() {
        @Override
        public void run() {
            int delay = 10000;

            while (true) {
                sleep(delay);
                sendAlive();

                // The first delay for sending an ALIVE message is 10 seconds,
                // the second delay is for 20 seconds. From then on, all other
                // delays are for 180 seconds.
                switch (delay) {
                case 10000:
                    delay = 20000;
                    break;
                case 20000:
                    delay = 180000;
                    break;
                }
            }
        }
    };

    aliveThread = new Thread(rAlive, "UPNP-AliveMessageSender");
    aliveThread.start();

    Runnable r = new Runnable() {
        @Override
        public void run() {
            boolean bindErrorReported = false;

            while (true) {
                MulticastSocket multicastSocket = null;

                try {
                    // Use configurable source port as per http://code.google.com/p/ps3mediaserver/issues/detail?id=1166
                    multicastSocket = new MulticastSocket(configuration.getUpnpPort());

                    if (bindErrorReported) {
                        logger.warn(
                                "Finally, acquiring port " + configuration.getUpnpPort() + " was successful!");
                    }

                    NetworkInterface ni = NetworkConfiguration.getInstance().getNetworkInterfaceByServerName();

                    try {
                        // Setting the network interface will throw a SocketException on Mac OSX
                        // with Java 1.6.0_45 or higher, but if we don't do it some Windows
                        // configurations will not listen at all.
                        if (ni != null) {
                            multicastSocket.setNetworkInterface(ni);
                        } else if (PMS.get().getServer().getNetworkInterface() != null) {
                            multicastSocket.setNetworkInterface(PMS.get().getServer().getNetworkInterface());
                            logger.trace("Setting multicast network interface: "
                                    + PMS.get().getServer().getNetworkInterface());
                        }
                    } catch (SocketException e) {
                        // Not setting the network interface will work just fine on Mac OSX.
                    }

                    multicastSocket.setTimeToLive(4);
                    multicastSocket.setReuseAddress(true);
                    InetAddress upnpAddress = getUPNPAddress();
                    multicastSocket.joinGroup(upnpAddress);

                    while (true) {
                        byte[] buf = new byte[1024];
                        DatagramPacket receivePacket = new DatagramPacket(buf, buf.length);
                        multicastSocket.receive(receivePacket);

                        String s = new String(receivePacket.getData());

                        InetAddress address = receivePacket.getAddress();

                        if (s.startsWith("M-SEARCH")) {
                            String remoteAddr = address.getHostAddress();
                            int remotePort = receivePacket.getPort();

                            if (configuration.getIpFiltering().allowed(address)) {
                                logger.trace(
                                        "Receiving a M-SEARCH from [" + remoteAddr + ":" + remotePort + "]");

                                if (StringUtils.indexOf(s,
                                        "urn:schemas-upnp-org:service:ContentDirectory:1") > 0) {
                                    sendDiscover(remoteAddr, remotePort,
                                            "urn:schemas-upnp-org:service:ContentDirectory:1");
                                }

                                if (StringUtils.indexOf(s, "upnp:rootdevice") > 0) {
                                    sendDiscover(remoteAddr, remotePort, "upnp:rootdevice");
                                }

                                if (StringUtils.indexOf(s, "urn:schemas-upnp-org:device:MediaServer:1") > 0) {
                                    sendDiscover(remoteAddr, remotePort,
                                            "urn:schemas-upnp-org:device:MediaServer:1");
                                }

                                if (StringUtils.indexOf(s, "ssdp:all") > 0) {
                                    sendDiscover(remoteAddr, remotePort,
                                            "urn:schemas-upnp-org:device:MediaServer:1");
                                }

                                if (StringUtils.indexOf(s, PMS.get().usn()) > 0) {
                                    sendDiscover(remoteAddr, remotePort, PMS.get().usn());
                                }
                            }
                        } else if (s.startsWith("NOTIFY")) {
                            String remoteAddr = address.getHostAddress();
                            int remotePort = receivePacket.getPort();

                            logger.trace("Receiving a NOTIFY from [" + remoteAddr + ":" + remotePort + "]");
                        }
                    }
                } catch (BindException e) {
                    if (!bindErrorReported) {
                        logger.error("Unable to bind to " + configuration.getUpnpPort()
                                + ", which means that PMS will not automatically appear on your renderer! "
                                + "This usually means that another program occupies the port. Please "
                                + "stop the other program and free up the port. "
                                + "PMS will keep trying to bind to it...[" + e.getMessage() + "]");
                    }

                    bindErrorReported = true;
                    sleep(5000);
                } catch (IOException e) {
                    logger.error("UPNP network exception", e);
                    sleep(1000);
                } finally {
                    if (multicastSocket != null) {
                        // Clean up the multicast socket nicely
                        try {
                            InetAddress upnpAddress = getUPNPAddress();
                            multicastSocket.leaveGroup(upnpAddress);
                        } catch (IOException e) {
                        }

                        multicastSocket.disconnect();
                        multicastSocket.close();
                    }
                }
            }
        }
    };

    listenerThread = new Thread(r, "UPNPHelper");
    listenerThread.start();
}

From source file:com.mozilla.SUTAgentAndroid.service.DoCommand.java

public String FTPGetFile(String sServer, String sSrcFileName, String sDstFileName, OutputStream out) {
    byte[] buffer = new byte[4096];
    int nRead = 0;
    long lTotalRead = 0;
    String sRet = sErrorPrefix + "FTP Get failed for " + sSrcFileName;
    String strRet = "";
    int reply = 0;
    FileOutputStream outStream = null;
    String sTmpDstFileName = fixFileName(sDstFileName);

    FTPClient ftp = new FTPClient();
    try {//from  w  w w . j  a v  a2 s. c o m
        ftp.connect(sServer);
        reply = ftp.getReplyCode();
        if (FTPReply.isPositiveCompletion(reply)) {
            ftp.login("anonymous", "b@t.com");
            reply = ftp.getReplyCode();
            if (FTPReply.isPositiveCompletion(reply)) {
                ftp.enterLocalPassiveMode();
                if (ftp.setFileType(FTP.BINARY_FILE_TYPE)) {
                    File dstFile = new File(sTmpDstFileName);
                    outStream = new FileOutputStream(dstFile);
                    FTPFile[] ftpFiles = ftp.listFiles(sSrcFileName);
                    if (ftpFiles.length > 0) {
                        long lFtpSize = ftpFiles[0].getSize();
                        if (lFtpSize <= 0)
                            lFtpSize = 1;

                        InputStream ftpIn = ftp.retrieveFileStream(sSrcFileName);
                        while ((nRead = ftpIn.read(buffer)) != -1) {
                            lTotalRead += nRead;
                            outStream.write(buffer, 0, nRead);
                            strRet = "\r" + lTotalRead + " of " + lFtpSize + " bytes received "
                                    + ((lTotalRead * 100) / lFtpSize) + "% completed";
                            out.write(strRet.getBytes());
                            out.flush();
                        }
                        ftpIn.close();
                        @SuppressWarnings("unused")
                        boolean bRet = ftp.completePendingCommand();
                        outStream.flush();
                        outStream.close();
                        strRet = ftp.getReplyString();
                        reply = ftp.getReplyCode();
                    } else {
                        strRet = sRet;
                    }
                }
                ftp.logout();
                ftp.disconnect();
                sRet = "\n" + strRet;
            } else {
                ftp.disconnect();
                System.err.println("FTP server refused login.");
            }
        } else {
            ftp.disconnect();
            System.err.println("FTP server refused connection.");
        }
    } catch (SocketException e) {
        sRet = e.getMessage();
        strRet = ftp.getReplyString();
        reply = ftp.getReplyCode();
        sRet += "\n" + strRet;
        e.printStackTrace();
    } catch (IOException e) {
        sRet = e.getMessage();
        strRet = ftp.getReplyString();
        reply = ftp.getReplyCode();
        sRet += "\n" + strRet;
        e.printStackTrace();
    }
    return (sRet);
}

From source file:de.innovationgate.wgpublisher.WGPDispatcher.java

private boolean dispatchFileWithCache(PublishingFile publishingFile, HttpServletRequest request,
        HttpServletResponse response, FileCache fileCache, long lastModified, String designEncoding,
        String contentType, WGPRequestPath path) throws HttpErrorException, IOException, WGAPIException {
    boolean outputHandled = false;
    byte[] data = fileCache.getFile(publishingFile, lastModified);

    // Serve from cache
    if (data != null) {
        try {// w  w w  .ja  v a2  s . co  m
            // B000041DA
            ByteArrayDataSource dataIn = new ByteArrayDataSource(data, publishingFile.getFileName(),
                    contentType);
            writeData(dataIn, request, response, publishingFile.getTextEncoding(), data.length,
                    publishingFile.getSourceHint(), true);
        } catch (java.net.SocketException exc) {
            _log.warn("Dispatch of cached file request failed bc. of socket error: " + exc.getMessage());
        } catch (java.io.IOException exc) {
            if (!exc.getClass().getName().equals("org.apache.catalina.connector.ClientAbortException")) {
                _log.warn("Dispatch of cached file request failed bc. of IO error: " + exc.getMessage());
            }
        }
        outputHandled = true;
    }

    // Try to put to cache, if below threshold
    else {

        // First test if the file is available
        if (!publishingFile.isAvailable()) {
            throw new HttpErrorException(404, "File not found: " + publishingFile.getName(),
                    path.getDatabaseKey());
        }

        // Look if file size is below cache threshold - if so, collect data and
        // put into cache, then serve
        long threshold = fileCache.getThreshold();
        long fileSize = publishingFile.getFileSize();
        if (fileSize != -1 && threshold >= fileSize) {

            // Put into cache
            InputStream inputStream = publishingFile.getInputStream();
            try {
                ByteArrayOutputStream outCache = new ByteArrayOutputStream((int) fileSize);
                WGUtils.inToOut(inputStream, outCache, 2048);
                data = outCache.toByteArray();
                fileCache.putFile(publishingFile, data, lastModified);
            } catch (java.net.SocketException exc) {
                _log.warn("Caching of file request failed bc. of socket error: " + exc.getMessage());
            } catch (java.io.IOException exc) {
                if (!exc.getClass().getName().equals("org.apache.catalina.connector.ClientAbortException")) {
                    _log.warn("Caching of file request failed bc. of IO error: " + exc.getMessage());
                }
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (Exception e) {
                    }
                }
            }

            // Writing from cache to out
            try {
                // B000041DA
                ByteArrayDataSource dataIn = new ByteArrayDataSource(data, publishingFile.getFileName(),
                        contentType);
                if (designEncoding != null) {
                    writeData(dataIn, request, response, designEncoding, data.length,
                            publishingFile.getSourceHint(), true);
                } else {
                    writeData(dataIn, request, response, null, data.length, publishingFile.getSourceHint(),
                            true);
                }
            } catch (java.net.SocketException exc) {
                _log.warn("Dispatch of file request failed bc. of socket error: " + exc.getMessage());
            } catch (java.io.IOException exc) {
                if (!exc.getClass().getName().equals("org.apache.catalina.connector.ClientAbortException")) {
                    _log.warn("Dispatch of file request failed bc. of IO error: " + exc.getMessage());
                }
            }

            outputHandled = true;

        }
    }
    return outputHandled;
}

From source file:de.innovationgate.wgpublisher.WGPDispatcher.java

private void dispatchResourceRequest(WGPRequestPath path, javax.servlet.http.HttpServletRequest request,
        javax.servlet.http.HttpServletResponse response) throws Exception {

    WGARequestInformation info = (WGARequestInformation) request
            .getAttribute(WGARequestInformation.REQUEST_ATTRIBUTENAME);
    if (info != null) {
        info.setType(WGARequestInformation.TYPE_RESOURCE);
    }/* w  w w . j  a  va  2s . c o  m*/

    // determine mimeType
    String resourcePath = path.getResourcePath();
    String mimeType = this.getServletContext().getMimeType(resourcePath);
    if (mimeType == null) {
        mimeType = "application/octet-stream";
    }
    response.setContentType(mimeType);

    File file = null;
    boolean isTemporaryDownload = false;
    if (path.getPathCommand().equals(WGPRequestPath.PATHCMD_TEMP_DOWNLOAD)) {
        String tempFileName = path.getResourcePath().substring(path.getResourcePath().lastIndexOf("/") + 1);
        TemporaryDownloadsMap temporaryDownloads = (TemporaryDownloadsMap) request.getSession()
                .getAttribute(SESSION_TEMPORARYDOWNLOADS);
        if (temporaryDownloads != null) {
            TemporaryDownload tempDownload = (TemporaryDownload) temporaryDownloads.get(tempFileName);
            if (tempDownload != null) {
                file = tempDownload.getTempFile().getFile();
                isTemporaryDownload = true;
            }
        }
    } else {
        file = new File(this.getServletContext().getRealPath("/"), path.getResourcePath());
    }

    if (file == null || !file.exists() || !file.isFile()) {
        throw new HttpErrorException(404, "File not found: " + path.getResourcePath(), null);
    }

    // / Set expiration time
    int fileExpirationMinutes = getCore().getWgaConfiguration().getCacheExpirationForStaticResources();
    if (fileExpirationMinutes > 0) {
        int fileExpirationSeconds = fileExpirationMinutes * 60;
        response.setHeader("Cache-Control", "max-age=" + fileExpirationSeconds + ", must-revalidate");
    }

    // determine lastModified
    // - last modified of binary response depends only on resource change
    // date
    // - last change date of textual response additionally depends on
    // character encoding change date
    long lastModified;
    if (isBinary(request, response)) {
        lastModified = file.lastModified();
    } else {
        lastModified = Math.max(file.lastModified(), _core.getCharacterEncodingLastModified());
    }
    if (browserCacheIsValid(request, lastModified, String.valueOf(lastModified))) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return;
    } else {
        response.setDateHeader("Last-Modified", lastModified);
        response.setHeader("ETag", '"' + String.valueOf(lastModified) + '"');
    }

    if (mimeType.startsWith("application/")) {
        response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
    }

    // Dispatch to file resource
    try {
        if (!"HEAD".equalsIgnoreCase(request.getMethod())) {
            DataSource in = null;
            int fileSize = 0;

            // We allow direct file dispatching only for temporary files. In
            // all other cases we use the servlet
            // context which will take care of file system security.
            if (isTemporaryDownload) {
                response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
                in = new URLDataSource(file.toURI().toURL());
                fileSize = (int) file.length();
            } else {
                in = new URLDataSource(this.getServletContext().getResource(resourcePath));
            }

            // B000041DA
            // write data to response - use UTF-8 when reading characters -
            // WGA resources are UTF-8 encoded
            writeData(in, request, response, "UTF-8", fileSize, null, true);
        }
    } catch (java.net.SocketException exc) {
        _log.warn("Dispatch of resource request failed bc. of socket error: " + exc.getMessage());
    } catch (java.io.IOException exc) {
        _log.warn("Dispatch of resource request failed bc. of IO error: " + exc.getMessage());
    }
}

From source file:de.innovationgate.wgpublisher.WGPDispatcher.java

private void dispatchCssjsRequest(WGPRequestPath path, javax.servlet.http.HttpServletRequest request,
        javax.servlet.http.HttpServletResponse response) throws java.lang.Exception {

    WGARequestInformation info = (WGARequestInformation) request
            .getAttribute(WGARequestInformation.REQUEST_ATTRIBUTENAME);
    if (info != null) {
        info.setType(WGARequestInformation.TYPE_SCRIPT);
    }/*from  w ww.  java2 s  . c o m*/

    // Fetch the database
    WGDatabase database = path.getDatabase();

    // Fetch the library
    String codeType;
    switch (path.getPathType()) {

    case WGPRequestPath.TYPE_CSS:
        codeType = WGScriptModule.CODETYPE_CSS;
        break;

    case WGPRequestPath.TYPE_JS:
        codeType = WGScriptModule.CODETYPE_JS;
        break;

    default:
        throw new HttpErrorException(500,
                "Invalid path type to dispatch a css/js request: " + path.getPathType(), path.getDatabaseKey());

    }

    WGCSSJSModule lib = database.getScriptModule(path.getCssjsKey(), codeType);
    if (lib == null) {
        if (codeType.equals(WGScriptModule.CODETYPE_CSS) && path.getCssjsKey().endsWith(".css")) {
            lib = database.getScriptModule(path.getCssjsKey().substring(0, path.getCssjsKey().length() - 4),
                    codeType);
        } else if (codeType.equals(WGScriptModule.CODETYPE_JS) && path.getCssjsKey().endsWith(".js")) {
            lib = database.getScriptModule(path.getCssjsKey().substring(0, path.getCssjsKey().length() - 3),
                    codeType);
        }
    }

    if (lib == null) {
        throw new HttpErrorException(404, "No css/js resource of name " + path.getCssjsKey(),
                path.getDatabaseKey());
    }

    // determine mime type and encoding
    String mimeType;
    String libType = lib.getCodeType();
    if (libType.equals(WGCSSJSModule.CODETYPE_CSS)) {
        mimeType = "text/css";
    } else if (libType.equals(WGCSSJSModule.CODETYPE_JS)) {
        mimeType = "text/javascript";
    } else {
        mimeType = "text/" + libType;
    }

    // Reading and post processing of code
    PostProcessResult result = postProcessDesignResource(lib, request, response);
    String code;
    if (result != null) {
        code = result.getCode();
        if (result.getMimeType() != null) {
            mimeType = result.getMimeType();
        }
    } else {
        code = lib.getCode();
    }

    response.setContentType(mimeType);

    // Set expiration time
    int fileExpirationMinutes = ((Integer) _core.readPublisherOptionOrDefault(database,
            WGACore.DBATTRIB_FILEEXPIRATION_MINUTES)).intValue();
    if (fileExpirationMinutes > 0) {
        int fileExpirationSeconds = fileExpirationMinutes * 60;
        boolean isAnonymousAccessible = database.isAnonymousAccessible();
        if (isAnonymousAccessible)
            response.setHeader("Cache-Control", "public, max-age=" + fileExpirationSeconds);
        else
            response.setHeader("Cache-Control", "private, max-age=" + fileExpirationSeconds);
    }

    // determine lastModified
    // - last modified of binary response depends only on resource change
    // date
    // - last change date of textual response additionally depends on
    // character encoding change date
    long lastModified;
    if (isBinary(request, response)) {
        lastModified = lib.getLastModified().getTime();
    } else {
        lastModified = Math.max(lib.getLastModified().getTime(), _core.getCharacterEncodingLastModified());
        lastModified = Math.max(lastModified, _core.getDesignEncodingLastModified(database.getDbReference()));
    }

    String eTag = String.valueOf(code.hashCode()) + "-"
            + String.valueOf(_core.getDesignEncodingLastModified(database.getDbReference()));
    if (browserCacheIsValid(request, null, eTag)) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        response.setHeader("ETag", '"' + eTag + '"');
        return;
    } else {
        response.setHeader("ETag", '"' + eTag + '"');
    }

    // If this is a head request we are finished now
    if ("HEAD".equalsIgnoreCase(request.getMethod())) {
        return;
    }

    try {
        java.io.Writer out = response.getWriter();
        out.write(code);
    } catch (java.net.SocketException exc) {
        _log.warn("Dispatch of css/js request failed bc. of socket error: " + exc.getMessage());
    } catch (java.io.IOException exc) {
        _log.warn("Dispatch of css/js request failed bc. of IO error: " + exc.getMessage());
    }
}

From source file:de.innovationgate.wgpublisher.WGPDispatcher.java

private void dispatchPublishingFile(PublishingFile publishingFile, HttpServletRequest request,
        HttpServletResponse response, String textOutputEncoding, FileCache fileCache, WGPRequestPath path)
        throws WGException, HttpErrorException, IOException {

    // Collect HTTP client hints (if enabled)
    ClientHints clientHints = new ClientHints();
    boolean useHttpClientHints = false;
    if (publishingFile.getDatabase() != null) {
        Database database = WGA.get(request, response, getCore()).database(publishingFile.getDatabase());
        if (database instanceof App
                && ((Boolean) database.getPublisherOption(WGACore.DBATTRIB_USE_NONFINAL_HT_FEATURES)) == true) {
            useHttpClientHints = true;/*  w  w w.j  ava  2s  . c  o m*/
        }
    }

    if (useHttpClientHints) {
        String dprStr = request.getHeader("CH-DPR");
        if (dprStr != null) {
            try {
                clientHints.setDevicePixelRatio(Float.valueOf(dprStr));
            } catch (NumberFormatException e) {
                getCore().getLog().warn("Client uses unparseable device pixel ratio: " + dprStr);
            }
        }
    }

    // Optionally select derivate
    Float usedDevicePixelRatio = null;
    try {

        String derivate = request.getParameter(URLPARAM_DERIVATE);
        if (derivate != null) {
            DerivateQuery derivateQuery = getCore().getFileDerivateManager().parseDerivateQuery(derivate);
            if (publishingFile instanceof DocumentPublishingFile) {
                DocumentPublishingFile docPublishingFile = (DocumentPublishingFile) publishingFile;
                WGFileDerivateMetaData derivateMd = docPublishingFile.queryDerivate(derivateQuery, clientHints);
                if (derivateMd != null) {
                    usedDevicePixelRatio = docPublishingFile.getUsedDevicePixelRatio();
                    publishingFile = new DerivatePublishingFile(this, docPublishingFile.getContainer(),
                            derivateMd);

                }
            } else if (!isFallbackToOriginalOnDerivateQuery(derivateQuery, publishingFile)) {
                throw new WGNotSupportedException("Derivate queries are not supported on this file type");
            }

        }

    } catch (WGNotSupportedException e) {
        throw new HttpErrorException(412, e.getMessage(), path.getDatabaseKey());
    } catch (WGInvalidDerivateQueryException e) {
        throw new HttpErrorException(400, "Invalid derivate query: " + e.getMessage(), path.getDatabaseKey());
    } catch (WGFailedDerivateQueryException e) {
        throw new HttpErrorException(412,
                "No derivate of file '" + publishingFile.getFileName() + "' matches the derivate query",
                path.getDatabaseKey());
    }

    // Put out the used device pixel ratio, if any
    if (usedDevicePixelRatio != null) {
        response.setHeader("Vary", "CH-DPR");
        response.setHeader("DPR", usedDevicePixelRatio.toString());
    }

    // Handle browser cache
    long lastModified = determinePublishingFileLastModified(publishingFile, request, response);

    if (browserCacheIsValid(request, lastModified, publishingFile.getETag())) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return;
    } else {
        response.setDateHeader("Last-Modified", lastModified);
        response.setHeader("ETag", '"' + publishingFile.getETag() + '"');
    }

    // Optionally inject online scaling information to file object
    String maxHeightStr = request.getParameter(URLPARAM_MAXHEIGHT);
    String maxWidthStr = request.getParameter(URLPARAM_MAXWIDTH);
    if (maxHeightStr != null || maxWidthStr != null) {
        try {
            int maxHeight = -1;
            if (maxHeightStr != null) {
                maxHeight = Integer.parseInt(maxHeightStr);
            }
            int maxWidth = -1;
            if (maxWidthStr != null) {
                maxWidth = Integer.parseInt(maxWidthStr);
            }
            publishingFile.setOnlineScaling(maxWidth, maxHeight, clientHints);
        } catch (NumberFormatException e) {
            getCore().getLog().error("Unparseable online scaling metrics", e);
        } catch (Exception e) {
            getCore().getLog().error("Exception setting online scaling information", e);
        }
    }

    // Put out content type
    String contentType = publishingFile.getContentType();
    if (contentType == null) {
        contentType = "application/octet-stream";
    }
    response.setContentType(contentType);

    // Content Disposition Header - Either if download forced or a disposition filename has been specified
    Boolean forceDownload = Boolean.parseBoolean(request.getParameter("forcedownload"));
    if (forceDownload) {
        response.setHeader("Content-disposition",
                "attachment" + (publishingFile.getDispositionFileName() != null
                        ? ";filename=" + publishingFile.getDispositionFileName()
                        : ""));
    } else if (publishingFile.getDispositionFileName() != null) {
        response.setHeader("Content-disposition", "inline;filename=" + publishingFile.getDispositionFileName());
    }

    // Allow accept ranges on all CS with optimized file handling and binary responses
    if (publishingFile.isAllowAcceptRanges() && isBinary(request, response)) {
        response.setHeader("Accept-Ranges", "bytes");
    }

    try {
        // Look if file is cached - If so, send it and exit
        if (fileCache != null) {
            boolean outputHandled = dispatchFileWithCache(publishingFile, request, response, fileCache,
                    lastModified, textOutputEncoding, contentType, path);
            if (outputHandled) {
                return;
            }
        }

        // We serve from cache so must retrieve the file. Test for availability now which may load the document.
        if (!publishingFile.isAvailable()) {
            throw new HttpErrorException(404, "File not found: " + publishingFile.getName(),
                    path.getDatabaseKey());
        }

        // File is above threshold and not in cache - serve from database
        writeData(publishingFile, request, response, publishingFile.getTextEncoding(),
                publishingFile.getFileSize(), publishingFile.getSourceHint(),
                publishingFile.isAllowAcceptRanges() && isBinary(request, response));
    } catch (java.net.SocketException exc) {
        _log.warn("Dispatch of file request failed bc. of socket error: " + exc.getMessage());
    } catch (java.io.IOException exc) {
        if (!exc.getClass().getName().equals("org.apache.catalina.connector.ClientAbortException")) {
            _log.warn("Dispatch of file request failed bc. of IO error: " + exc.getMessage());
        }
    } catch (HttpErrorException exc) {
        throw exc;
    } catch (Exception exc) {
        _log.error("Exception dispatching file " + publishingFile.getName(), exc);
    }
}

From source file:rems.Global.java

public static String UploadFile(InetAddress ftpserverurl, String serverAppDirectory, String PureFileName,
        String fullLocFileUrl, String userName, String password) {
    // get an ftpClient object  
    FTPClient ftpClient = new FTPClient();
    FileInputStream inputStream = null;
    String responsTxt = "";
    try {/*from  ww w  .j  a  va 2  s. c  o m*/
        // pass directory path on server to connect
        // pass username and password, returned true if authentication is  
        // successful  
        ftpClient.connect(ftpserverurl, 21);
        boolean login = ftpClient.login(userName, password);
        ftpClient.setKeepAlive(false);
        ftpClient.setPassiveNatWorkaround(true);
        if (login) {
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            File firstLocalFile = new File(fullLocFileUrl);
            inputStream = new FileInputStream(firstLocalFile);
            //inputStream.reset();
            boolean uploaded = ftpClient.storeFile(serverAppDirectory + PureFileName, inputStream);
            inputStream.close();
            responsTxt = ftpClient.getReplyString();
            if (uploaded) {
                responsTxt += "File uploaded successfully !";
            } else {
                responsTxt += "Error in uploading file !::" + serverAppDirectory + PureFileName;
            }

            Global.updateLogMsg(Global.logMsgID, "\r\n\r\n\r\nUpload Response ==>\r\n" + responsTxt,
                    Global.logTbl, Global.gnrlDateStr, Global.rnUser_ID);
            // logout the user, returned true if logout successfully  
            boolean logout = ftpClient.logout();
            if (logout) {
                //System.out.println("Connection close...");
            }
        } else {
            Global.errorLog += "Connection Failed..." + responsTxt;
            Global.updateLogMsg(Global.logMsgID,
                    "\r\n\r\n\r\nThe Program has Errored Out ==>\r\n\r\n" + Global.errorLog, Global.logTbl,
                    Global.gnrlDateStr, Global.rnUser_ID);
            Global.writeToLog();
        }
        return responsTxt;
    } catch (SocketException e) {
        Global.errorLog += e.getMessage() + "\r\n" + Arrays.toString(e.getStackTrace());
        Global.updateLogMsg(Global.logMsgID,
                "\r\n\r\n\r\nThe Program has Errored Out ==>\r\n\r\n" + Global.errorLog, Global.logTbl,
                Global.gnrlDateStr, Global.rnUser_ID);
        Global.writeToLog();
    } catch (IOException e) {
        Global.errorLog += e.getMessage() + "\r\n" + Arrays.toString(e.getStackTrace());
        Global.updateLogMsg(Global.logMsgID,
                "\r\n\r\n\r\nThe Program has Errored Out ==>\r\n\r\n" + Global.errorLog, Global.logTbl,
                Global.gnrlDateStr, Global.rnUser_ID);
        Global.writeToLog();
    } finally {
        try {
            ftpClient.disconnect();
        } catch (IOException e) {
            Global.errorLog += e.getMessage() + "\r\n" + Arrays.toString(e.getStackTrace());
            Global.updateLogMsg(Global.logMsgID,
                    "\r\n\r\n\r\nThe Program has Errored Out ==>\r\n\r\n" + Global.errorLog, Global.logTbl,
                    Global.gnrlDateStr, Global.rnUser_ID);
            Global.writeToLog();
        } finally {

        }
    }
    return "";
}

From source file:com.microsoft.tfs.core.clients.versioncontrol.VersionControlClient.java

/**
 * Download the file described by spec to the destination stream or streams.
 * <p>//w  w w . j a  va 2 s.  co m
 * <h3>Notice:</h3>
 * <p>
 * This method can only recover from transient network problems (TCP socket
 * resets) if all {@link DownloadOutput}s support stream reset. Download
 * proxy connect errors do not require output stream reset because not data
 * will have been written to them yet.
 * <p>
 * The output streams are always left open (they may have been reset, but no
 * effort is made to finally close them), even when an exception is thrown.
 *
 * @param spec
 *        the spec that describes the file to download (must not be
 *        <code>null</code>)
 * @param outputs
 *        the outputs where the downloaded data will be written (must not be
 *        <code>null</code> or empty)
 * @param eventSource
 *        a custom {@link EventSource} or <code>null</code> to use
 *        {@link EventSource#newFromHere()}
 * @param taskMonitor
 *        a custom {@link TaskMonitor} or <code>null</code> to use the
 *        monitor from the {@link TaskMonitorService}
 * @throws CanceledException
 *         if the download was cancelled by the user via core's
 *         {@link TaskMonitor}. The output streams may have had some data
 *         written to them.
 */
public void downloadFileToStreams(final DownloadSpec spec, final DownloadOutput[] outputs,
        EventSource eventSource, final TaskMonitor taskMonitor) throws CanceledException {
    Check.notNull(spec, "spec"); //$NON-NLS-1$
    Check.notNullOrEmpty(outputs, "outputs"); //$NON-NLS-1$

    final int maxRetry = Integer.getInteger(MAX_REQUEST_RETRY_PROPERTY, MAX_REQUEST_RETRY_DEFAULT);

    if (eventSource == null) {
        eventSource = EventSource.newFromHere();
    }

    /*
     * This method aims to be tolerant of connection resets caused by
     * half-open sockets. It detects them and retries the operation once.
     * See the full notes in
     * com.microsoft.tfs.core.ws.runtime.client.SOAPService
     * #executeSOAPRequest about why this can happen when talking to IIS.
     *
     * Some JREs use the string "Connection reset by peer", others use
     * "Connection reset". We will match both.
     *
     * As soon as an exception is caught, we remember that we had that type
     * of exception, then let the loop retry. Second time we hit that same
     * exception we throw it.
     *
     * Also retry when when the download proxy is unavailable.
     */

    boolean hadDownloadProxyException = false;
    boolean hadSocketException = false;

    for (int retryCount = 1; retryCount <= maxRetry; retryCount++) {
        log.info("File download attempt " + retryCount); //$NON-NLS-1$

        try {
            // Don't reset for proxy error; no data would have been written
            if (hadSocketException) {
                resetOutputs(outputs);
            }

            downloadFileToStreamsInternal(spec, outputs, taskMonitor);

            /*
             * This breaks from the loop in the success case.
             */
            return;
        } catch (final SocketException e) {
            log.warn("SocketException for " + spec.getQueryString(), e); //$NON-NLS-1$
            /*
             * If this fault was not a TCP connection reset, rethrow it.
             * Weeds out non-retryable socket exceptions.
             */
            if (!e.getMessage().startsWith("Connection reset")) //$NON-NLS-1$
            {
                throw new VersionControlException(e);
            }

            if (retryCount == maxRetry) {
                log.warn(MessageFormat.format("Max retry reached {0}, not trying any longer", //$NON-NLS-1$
                        spec.getQueryString()));
                throw new VersionControlException(e);
            } else {
                hadSocketException = true;
            }

            log.warn(
                    MessageFormat.format("Retrying download after a connection reset for {0}", //$NON-NLS-1$
                            spec.getQueryString()), e);
        } catch (final SocketTimeoutException e) {
            log.warn("SocketTimeoutException for " + spec.getQueryString(), e); //$NON-NLS-1$

            if (retryCount == maxRetry) {
                log.warn(MessageFormat.format("Max retry reached {0}, not trying any longer", //$NON-NLS-1$
                        spec.getQueryString()));
                throw new VersionControlException(e);
            } else {
                hadSocketException = true;
            }

            log.warn(
                    MessageFormat.format("Retrying download after a socket timeout for {0}", //$NON-NLS-1$
                            spec.getQueryString()), e);
        } catch (final DownloadProxyException e) {
            /*
             * Since we call recordDownloadProxyFailure, we should never
             * have another of these during a retry, but the check is
             * probably valuable to prevent an infinite loop.
             */
            if (hadDownloadProxyException) {
                log.warn(MessageFormat.format(
                        "Second download proxy error for {0}, which should never happen because we disabled the download proxy, rethrowing", //$NON-NLS-1$
                        spec.getQueryString()));
                throw new VersionControlException(e);
            } else {
                hadDownloadProxyException = true;
            }

            log.warn(MessageFormat.format("Download proxy error for {0}, disabling for this session", //$NON-NLS-1$
                    spec.getQueryString()));

            /*
             * The download proxy exception has a nice message in it, but we
             * need to let the user know we'll retry.
             */
            getEventEngine().fireNonFatalError(new NonFatalErrorEvent(eventSource, this, e));
            getEventEngine().fireNonFatalError(new NonFatalErrorEvent(eventSource, this,
                    new DownloadProxyException(
                            //@formatter:off
                            Messages.getString(
                                    "VersionControlClient.DisablingDownloadProxyForThisSessionAndRetrying")))); //$NON-NLS-1$
            //@formatter:on
            recordDownloadProxyFailure();
        } catch (final IOException e) {
            /*
             * This is an exception from resetting the streams after a retry
             * (probably because the output doesn't support stream reset).
             * Just rethrow.
             */
            log.warn("Fatal IOException stops download retries", e); //$NON-NLS-1$
            throw new VersionControlException(e);
        }

        // Let the loop retry the download.

        final long delayTime = 10000 * (long) Math.pow(2, retryCount - 1);
        log.info("Retrying request in " + delayTime + " ms"); //$NON-NLS-1$ //$NON-NLS-2$
        try {
            Thread.sleep(delayTime);
        } catch (final InterruptedException e) {
            log.debug("Sleeping thred has been interrupted", e); //$NON-NLS-1$
            throw new VersionControlException(e);
        }
    }
}

From source file:org.witness.ssc.xfer.utils.PublishingUtils.java

public Thread videoUploadToFTPserver(final Activity activity, final Handler handler,
        final String latestVideoFile_filename, final String latestVideoFile_absolutepath,
        final String emailAddress, final long sdrecord_id) {

    Log.d(TAG, "doVideoFTP starting");

    // Make the progress bar view visible.
    ((SSCXferActivity) activity).startedUploading();

    final Resources res = activity.getResources();

    Thread t = new Thread(new Runnable() {
        public void run() {
            // Do background task.
            // FTP; connect preferences here!
            ////  w w  w .  j ava  2  s .co  m
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity.getBaseContext());
            String ftpHostName = prefs.getString("defaultFTPhostPreference", null);
            String ftpUsername = prefs.getString("defaultFTPusernamePreference", null);
            String ftpPassword = prefs.getString("defaultFTPpasswordPreference", null);

            // use name of local file.
            String ftpRemoteFtpFilename = latestVideoFile_filename;

            // FTP
            FTPClient ftpClient = new FTPClient();
            InetAddress uploadhost = null;
            try {

                uploadhost = InetAddress.getByName(ftpHostName);
            } catch (UnknownHostException e1) {
                // If DNS resolution fails then abort immediately - show
                // dialog to
                // inform user first.
                e1.printStackTrace();
                Log.e(TAG, " got exception resolving " + ftpHostName + " - video uploading failed.");
                uploadhost = null;
            }

            if (uploadhost == null) {

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        new AlertDialog.Builder(activity).setMessage(R.string.cant_find_upload_host)
                                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {

                                    }
                                })

                                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {

                                    }
                                }).show();

                    }
                }, 0);

                return;
            }

            boolean connected = false;

            try {
                ftpClient.connect(uploadhost);
                connected = true;

            } catch (SocketException e) {
                e.printStackTrace();
                connected = false;

            } catch (UnknownHostException e) {
                //
                e.printStackTrace();
                connected = false;
            } catch (IOException e) {
                //
                e.printStackTrace();
                connected = false;
            }

            if (!connected) {

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        new AlertDialog.Builder(activity).setMessage(R.string.cant_login_upload_host)
                                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {

                                    }
                                })

                                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {

                                    }
                                }).show();

                    }
                }, 0);

                return;
            }

            boolean reply = false;
            try {

                reply = ftpClient.login(ftpUsername, ftpPassword);
            } catch (IOException e) {
                //
                e.printStackTrace();
                Log.e(TAG, " got exception on ftp.login - video uploading failed.");
            }

            // check the reply code here
            // If we cant login, abort after showing user a dialog.
            if (!reply) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                }

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        new AlertDialog.Builder(activity).setMessage(R.string.cant_login_upload_host)
                                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int whichButton) {

                                    }
                                }).show();
                    }
                }, 0);

                return;
            }

            // Set File type to binary
            try {
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            } catch (IOException e) {
                //
                e.printStackTrace();
                // keep going?!
            }

            // BEYOND HERE DONT USE DIALOGS!

            // Construct the input stream to send to Ftp server, from the
            // local
            // video file on the sd card
            BufferedInputStream buffIn = null;
            File file = new File(latestVideoFile_absolutepath);

            try {
                buffIn = new BufferedInputStream(new FileInputStream(file));
            } catch (FileNotFoundException e) {
                //
                e.printStackTrace();
                Log.e(TAG, " got exception on local video file - video uploading failed.");

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                    }
                }, 0);

                // This is a bad error, lets abort.
                // user dialog ?! shouldnt happen, but still...
                return;
            }

            ftpClient.enterLocalPassiveMode();

            try {
                // UPLOAD THE LOCAL VIDEO FILE.
                ftpClient.storeFile(ftpRemoteFtpFilename, buffIn);
            } catch (IOException e) {
                //
                e.printStackTrace();
                Log.e(TAG, " got exception on storeFile - video uploading failed.");

                // This is a bad error, lets abort.
                // user dialog ?! shouldnt happen, but still...
                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                    }
                }, 0);
                return;
            }
            try {
                buffIn.close();
            } catch (IOException e) {
                //
                e.printStackTrace();
                Log.e(TAG, " got exception on buff.close - video uploading failed.");

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                    }
                }, 0);
                return;
            }
            try {
                ftpClient.logout();
            } catch (IOException e) {
                //
                e.printStackTrace();
                Log.e(TAG, " got exception on ftp logout - video uploading failed.");

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                    }
                }, 0);
                return;
            }
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                //
                e.printStackTrace();
                Log.e(TAG, " got exception on ftp disconnect - video uploading failed.");

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Hide the progress bar
                        ((SSCXferActivity) activity).finishedUploading(false);
                        ((SSCXferActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                    }
                }, 0);
                return;
            }

            if (emailAddress != null && ftpHostName != null) {

                // EmailSender through IR controlled gmail system.
                SSLEmailSender sender = new SSLEmailSender(
                        activity.getString(R.string.automatic_email_username),
                        activity.getString(R.string.automatic_email_password)); // consider
                // this
                // public
                // knowledge.
                try {
                    sender.sendMail(activity.getString(R.string.vidiom_automatic_email), // subject.getText().toString(),
                            activity.getString(R.string.url_of_hosted_video_is_) + " " + ftpHostName, // body.getText().toString(),
                            activity.getString(R.string.automatic_email_from), // from.getText().toString(),
                            emailAddress // to.getText().toString()
                    );
                } catch (Exception e) {
                    Log.e(TAG, e.getMessage(), e);
                }
            }

            // Log record of this URL in POSTs table
            dbutils.creatHostDetailRecordwithNewVideoUploaded(sdrecord_id, ftpHostName, ftpHostName, "");

            // Use the handler to execute a Runnable on the
            // main thread in order to have access to the
            // UI elements.
            handler.postDelayed(new Runnable() {
                public void run() {
                    // Update UI

                    // Indicate back to calling activity the result!
                    // update uploadInProgress state also.

                    ((SSCXferActivity) activity).finishedUploading(true);
                    ((SSCXferActivity) activity)
                            .createNotification(res.getString(R.string.upload_to_ftp_host_succeeded_));

                }
            }, 0);

        }
    });

    t.start();

    return t;
}