List of usage examples for java.net SocketException getMessage
public String getMessage()
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; }