/**
  * This method validates input and then attempts to update the cheat sheet for the specified
  * module
  *
  * @param newSolution The new solution to store as a cheat sheet
  * @param moduleId[] The identifier of the module to update.
  * @param csrfToken
  */
 public void doPost(HttpServletRequest request, HttpServletResponse response)
     throws ServletException, IOException {
   // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
   ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
   log.debug("*** servlets.Admin.CreateCheat ***");
   Encoder encoder = ESAPI.encoder();
   PrintWriter out = response.getWriter();
   out.print(getServletInfo());
   HttpSession ses = request.getSession(true);
   Cookie tokenCookie = Validate.getToken(request.getCookies());
   Object tokenParmeter = request.getParameter("csrfToken");
   if (Validate.validateAdminSession(ses, tokenCookie, tokenParmeter)) {
     ShepherdLogManager.setRequestIp(
         request.getRemoteAddr(),
         request.getHeader("X-Forwarded-For"),
         ses.getAttribute("userName").toString());
     log.debug("Current User: "******"userName").toString());
     if (Validate.validateTokens(tokenCookie, tokenParmeter)) {
       String errorMessage = null;
       String newSolution = request.getParameter("newSolution");
       log.debug("User submitted new solution - " + newSolution);
       String moduleId = request.getParameter("moduleId[]");
       log.debug("User submitted moduleId: " + moduleId);
       if (newSolution != null && !newSolution.isEmpty()) {
         String ApplicationRoot = getServletContext().getRealPath("");
         String moduleCheck = Getter.getModuleResult(ApplicationRoot, moduleId);
         if (moduleCheck != null) {
           if (!Setter.updateCheatSheet(
               ApplicationRoot, moduleId, encoder.encodeForHTML(newSolution)))
             errorMessage = "A database level error occurred. Please contact your administrator";
         } else {
           errorMessage = "Invalid Module submitted";
         }
       } else {
         errorMessage = "Invalid Module submitted";
       }
       String output = new String();
       if (errorMessage != null) {
         output =
             "<h2 class='title'>Create Cheat Sheet Failure</h2>"
                 + "<p>"
                 + encoder.encodeForHTML(errorMessage)
                 + "</p>";
       } else {
         output =
             "<h2 class='title'>Create Cheat Sheet Success</h2>"
                 + "<p>Cheat Sheet successfully created</p>";
       }
       out.write(output);
     }
   } else {
     out.write("<img src='css/images/loggedOutSheep.jpg'/>");
   }
   log.debug("*** END servlets.Admin.CreateCheat ***");
 }
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    log.debug("&&& servlets.module.SolutionSubmit &&&");
    PrintWriter out = response.getWriter();
    out.print(getServletInfo());
    HttpSession ses = request.getSession(true);
    if (Validate.validateSession(ses)) {
      ShepherdLogManager.setRequestIp(
          request.getRemoteAddr(),
          request.getHeader("X-Forwarded-For"),
          ses.getAttribute("userName").toString());
      log.debug("Current User: "******"userName").toString());
      Cookie tokenCookie = Validate.getToken(request.getCookies());
      Object tokenParmeter = request.getParameter("csrfToken");
      if (Validate.validateTokens(tokenCookie, tokenParmeter)) {
        boolean notNull = false;
        String storedResult = null;
        try {
          log.debug("Getting ApplicationRoot");
          String ApplicationRoot = getServletContext().getRealPath("");
          log.debug("Servlet root = " + ApplicationRoot);

          log.debug("Getting Parameters");
          String moduleId = (String) request.getParameter("moduleId");
          ;
          log.debug("moduleId = " + moduleId.toString());
          String solutionKey = (String) request.getParameter("solutionKey");
          ;
          log.debug("solutionKey = " + solutionKey.toString());

          log.debug("Getting session parameters");
          String userId = (String) ses.getAttribute("userStamp");
          String userName = (String) ses.getAttribute("userName");
          log.debug("userId = " + userId);

          // Validation
          notNull = (moduleId != null && solutionKey != null);
          if (notNull) {
            storedResult = Getter.getModuleResult(ApplicationRoot, moduleId);
          }
          if (notNull && storedResult != null) {
            boolean validKey = false;
            // Identify if solution is a user Specific key (Does it need to be decrypted?)
            if (Getter.getModuleKeyType(ApplicationRoot, moduleId))
              validKey = storedResult.compareTo(solutionKey) == 0;
            else {
              String decryptedKey = new String();
              try {
                // Encrypted Solution key,  must be decrypted before compare
                decryptedKey =
                    Hash.decryptUserSpecificSolution(
                        Validate.validateEncryptionKey(userName), solutionKey);
              } catch (Exception e) {
                log.error("Could not decrypt result key: " + e.toString());
                // Key likely could not be decrypted because somebody submitted a string that could
                // not be decrypted.
                // This is a bad submission so they should be warned. String will continue from this
                // point as an empty value and will cause the function to run the Bad Submission
                // procedure
              }
              storedResult +=
                  Hash.getCurrentSalt(); // Add server solution salt to base key before compare with
              // decrypted key
              validKey = storedResult.compareTo(decryptedKey) == 0;
              log.debug("Decrypted Submitted Key: " + decryptedKey);
              log.debug("Stored Expected Key    : " + storedResult);
            }
            if (validKey) {
              log.debug("Correct key submitted, checking that module not already completed");
              String result = Getter.checkPlayerResult(ApplicationRoot, moduleId, userId);
              if (result != null) {
                // If Feedback is enabled, the user must complete another step. This step is
                // continued in FeedbackSubmit.java
                if (FeedbackStatus.isEnabled()) {
                  log.debug("Returning Feedback Form for module: " + result);
                  out.write(
                      "<h2 class=\"title\">Solution Submission Success</h2><br>"
                          + "<p> You are one step away from completing <a>"
                          + encoder.encodeForHTML(result)
                          + "</a>! To complete the level please submit your feedback!"
                          + "</p><br/>"
                          + generateFeedbackForm(moduleId, (String) tokenParmeter, solutionKey));
                } else // Feedback is disabled
                {
                  log.debug("Feedback is disabled, Marking as completed");
                  String htmlOutput = new String();
                  result =
                      Setter.updatePlayerResult(
                          ApplicationRoot, moduleId, userId, "Feedback is Disabled", 1, 1, 1);
                  if (result != null) {
                    ResourceBundle bundle =
                        ResourceBundle.getBundle(
                            "i18n.moduleGenerics.moduleNames",
                            new Locale(Validate.validateLanguage(request.getSession())));
                    String compltedModuleLocalName = bundle.getString(result);
                    log.debug(
                        "Solution Submission for module " + compltedModuleLocalName + " succeeded");
                    htmlOutput =
                        new String(
                            "<h2 class=\"title\">Solution Submission Success</h2><br>"
                                + "<p>"
                                + compltedModuleLocalName
                                + " completed! Congratulations.");
                    htmlOutput += "</p>";
                    // Refresh Side Menu
                    htmlOutput +=
                        FeedbackSubmit.refreshMenuScript(
                            encoder.encodeForHTML((String) tokenParmeter), "Refresh Error");
                    log.debug("Resetting user's Bad Submisison count to 0");
                    Setter.resetBadSubmission(ApplicationRoot, userId);
                    out.write(htmlOutput);
                  } else {
                    htmlOutput = new String("Could not update user result");
                    out.print(
                        "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                            + "<p><font color=\"red\">"
                            + "Sorry but an error Occurred!"
                            + "</font></p>");
                  }
                }
              } else {
                log.error("User has completed this module before. Returning Error");
                out.write(
                    "<h2 class=\"title\">Haven't You Done This Already?</h2><br>"
                        + "<p>"
                        + "Our records say you have already completed this module! Go try another one!"
                        + "</p>");
              }
            } else {
              log.error("Incorrect key submitted, returning error");
              out.print(
                  "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                      + "<p><font color=\"red\">"
                      + "Incorrect Solution Key Submitted.<br><br>You have limited amounts of incorrect key submissions before you will loose 10% of your points. Contact the OWASP Security Shepherd if you think you have found the correct key but it is failing you."
                      + "</font></p>");

              log.error("Invoking Bad Submission procedure...");
              Setter.incrementBadSubmission(ApplicationRoot, userId);
              log.error(userName + " has been warned and potentially has lost points");
            }
          } else {
            // Validation Error Responses
            String errorMessage = "An Error Occurred: ";
            if (!notNull) {
              log.error("Null values detected");
              errorMessage += "Invalid Request. Please try again";
            } else if (storedResult == null) {
              log.error("Module not found");
              errorMessage += "Module Not Found. Please try again";
            }
            out.print(
                "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                    + "<p><font color=\"red\">"
                    + encoder.encodeForHTML(errorMessage)
                    + "</font><p>");
          }
        } catch (Exception e) {
          log.error("Solution Submission Error: " + e.toString());
          out.print(
              "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                  + "<p>"
                  + "<font color=\"red\">An error Occurred! Please try again.</font>"
                  + "<p>");
        }
      } else {
        log.debug("CSRF Tokens did not match");
        out.print(
            "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                + "<p>"
                + "<font color=\"red\">An error Occurred! Please try again.</font>"
                + "<p>");
      }
    } else {
      out.print(
          "<h2 class=\"title\">Solution Submission Failure</h2><br>"
              + "<p>"
              + "<font color=\"red\">An error Occurred! Please Log in!</font>"
              + "<p>");
    }
    log.debug("&&& END SolutionSubmit &&&");
  }
  /**
   * Initiated by index.jsp, getStarted.jsp. This changes a users password. If the user gets it
   * wrong 3 times in a row, they'll be locked out (This is handed by database)
   *
   * @param csrfToken
   * @param currentPassword User's current password
   * @param newPassword Submitted new password
   * @param passwordConfirmation Confirmation of the new password
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    log.debug("*** servlets.ChangePassword ***");
    try {
      HttpSession ses = request.getSession(true);
      if (Validate.validateSession(ses)) {
        ShepherdLogManager.setRequestIp(
            request.getRemoteAddr(),
            request.getHeader("X-Forwarded-For"),
            ses.getAttribute("userName").toString());
        log.debug("Current User: "******"userName").toString());
        Cookie tokenCookie = Validate.getToken(request.getCookies());
        Object tokenParmeter = request.getParameter("csrfToken");
        if (Validate.validateTokens(tokenCookie, tokenParmeter)) {
          log.debug("Getting Parameters");
          String userName = (String) ses.getAttribute("userName");
          String currentPassword = (String) request.getParameter("currentPassword");
          String newPassword = (String) request.getParameter("newPassword");
          String passwordConfirm = (String) request.getParameter("passwordConfirmation");
          String ApplicationRoot = getServletContext().getRealPath("");

          boolean validData = false;
          boolean passwordChange = false;
          boolean validPassword = false;
          validData =
              newPassword.equalsIgnoreCase(passwordConfirm)
                  && !newPassword.isEmpty()
                  && newPassword != null;
          passwordChange = !currentPassword.equalsIgnoreCase(newPassword);
          validPassword = newPassword.length() > 4 && newPassword.length() <= 512;
          if (validData && passwordChange && validPassword) {
            log.debug("Validating Current Password");
            String user[] = Getter.authUser(ApplicationRoot, userName, currentPassword);
            if (user != null) {
              log.debug("User Credentials were good! Password Change gets the go ahead");
              Setter.updatePassword(ApplicationRoot, userName, currentPassword, newPassword);
              ses.setAttribute("ChangePassword", "false");
            } else {
              log.error("Incorrect Password");
              ses.setAttribute("errorMessage", "Incorrect Password... Don't lock yourself out!");
              response.sendRedirect("index.jsp");
            }
          } else {
            if (validData && passwordChange) {
              try {
                // User Account is Locked
                log.debug("The user account is locked. Logging the user out");
                Cookie cookieToken = Validate.getToken(request.getCookies());
                BigInteger temp = new BigInteger(cookieToken.getValue());
                response.sendRedirect("logout?csrfToken=" + temp);
              } catch (Exception e) {
                log.error(
                    "Cant Log the user out because they dont have a valid CSRF token : "
                        + e.toString());
                response.sendRedirect("login.jsp");
              }
            }
            // Return error message
            else if (!validData) {
              log.error("Bad Data Received");
              ses.setAttribute("errorMessage", "Invalid Request! Please try again.");
            } else if (!validPassword) {
              log.error("Invalid Password Submitted (Too Short/Long)");
              ses.setAttribute("errorMessage", "Invalid Password! Please try again.");
            } else {
              log.error("No password Change Detected");
              ses.setAttribute(
                  "errorMessage", "You have to CHANGE your password! Please try again.");
            }
          }
        } else {
          log.error("CSRF Attack Detected");
        }
      } else {
        log.error("Change Password Function Called with no valid session");
        response.sendRedirect("login.jsp");
      }
    } catch (Exception e) {
      log.fatal("ChangePassword Error: " + e.toString());
    }
    log.debug("*** END ChangePassword ***");
    response.sendRedirect("index.jsp");
  }