better config input validation, fixes resetting of checkboxes to default values on invalid input

pull/42/head
Zlatin Balevsky 2020-03-19 20:20:41 +00:00
parent db91c9171d
commit 9646eadcb1
2 changed files with 87 additions and 31 deletions

View File

@ -5,6 +5,8 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
@ -17,12 +19,38 @@ import com.muwire.core.Core;
public class ConfigurationServlet extends HttpServlet {
private static final Map<String, InputValidator> INPUT_VALIDATORS = new HashMap<>();
static {
INPUT_VALIDATORS.put("trustListInterval", new PositiveIntegerValidator("Trust list update frequency (hours)"));
INPUT_VALIDATORS.put("downloadRetryInterval", new PositiveIntegerValidator("Download retry frequency (seconds)"));
INPUT_VALIDATORS.put("totalUploadSlots", new IntegerValidator("Total upload slots (-1 means unlimited)"));
INPUT_VALIDATORS.put("uploadSlotsPerUser", new IntegerValidator("Upload slots per user (-1 means unlimited)"));
INPUT_VALIDATORS.put("downloadLocation", new DirectoryValidator());
INPUT_VALIDATORS.put("incompleteLocation", new DirectoryValidator());
INPUT_VALIDATORS.put("speedSmoothSeconds", new PositiveIntegerValidator("Download speed smoothing interval (seconds)"));
INPUT_VALIDATORS.put("inbound.length", new PositiveIntegerValidator("Inbound tunnel length"));
INPUT_VALIDATORS.put("inbound.quantity", new PositiveIntegerValidator("Inbound tunnel quantity"));
INPUT_VALIDATORS.put("outbound.length", new PositiveIntegerValidator("Outbound tunnel length"));
INPUT_VALIDATORS.put("outbound.quantity", new PositiveIntegerValidator("Outbound tunnel quantity"));
INPUT_VALIDATORS.put("defaultFeedUpdateInterval", new PositiveIntegerValidator("Feed update frequency (minutes)"));
INPUT_VALIDATORS.put("defaultFeedItemsToKeep", new IntegerValidator("Number of items to keep on disk (-1 means unlimited)"));
}
private Core core;
private ServletContext context;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
Enumeration<String> parameterNames = req.getParameterNames();
while(parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();
InputValidator iv = INPUT_VALIDATORS.get(name);
if (iv != null)
iv.validate(req.getParameter(name));
}
clearAllBooleans();
Enumeration<String> patameterNames = req.getParameterNames();
@ -49,8 +77,8 @@ public class ConfigurationServlet extends HttpServlet {
core.getMuOptions().setShareHiddenFiles(false);
core.getMuOptions().setSearchComments(false);
core.getMuOptions().setBrowseFiles(false);
core.getMuOptions().setFileFeed(true);
core.getMuOptions().setAdvertiseFeed(true);
core.getMuOptions().setFileFeed(false);
core.getMuOptions().setAdvertiseFeed(false);
core.getMuOptions().setAutoPublishSharedFiles(false);
core.getMuOptions().setDefaultFeedAutoDownload(false);
core.getMuOptions().setDefaultFeedSequential(false);
@ -61,58 +89,85 @@ public class ConfigurationServlet extends HttpServlet {
case "allowUntrusted" : core.getMuOptions().setAllowUntrusted(false); break;
case "searchExtraHop" : core.getMuOptions().setSearchExtraHop(true); break;
case "allowTrustLists": core.getMuOptions().setAllowTrustLists(true); break;
case "trustListInterval" : core.getMuOptions().setTrustListInterval(getPositiveInteger(value,"Trust list update frequency (hours)")); break;
case "downloadRetryInterval" : core.getMuOptions().setDownloadRetryInterval(getPositiveInteger(value,"Download retry frequency (seconds)")); break;
case "totalUploadSlots" : core.getMuOptions().setTotalUploadSlots(getInteger(value,"Total upload slots (-1 means unlimited)")); break;
case "uploadSlotsPerUser" : core.getMuOptions().setUploadSlotsPerUser(getInteger(value,"Upload slots per user (-1 means unlimited)")); break;
case "trustListInterval" : core.getMuOptions().setTrustListInterval(Integer.parseInt(value)); break;
case "downloadRetryInterval" : core.getMuOptions().setDownloadRetryInterval(Integer.parseInt(value)); break;
case "totalUploadSlots" : core.getMuOptions().setTotalUploadSlots(Integer.parseInt(value)); break;
case "uploadSlotsPerUser" : core.getMuOptions().setUploadSlotsPerUser(Integer.parseInt(value)); break;
case "downloadLocation" : core.getMuOptions().setDownloadLocation(getDirectory(value)); break;
case "incompleteLocation" : core.getMuOptions().setIncompleteLocation(getDirectory(value)); break;
case "shareDownloadedFiles" : core.getMuOptions().setShareDownloadedFiles(true); break;
case "shareHiddenFiles" : core.getMuOptions().setShareHiddenFiles(true); break;
case "searchComments" : core.getMuOptions().setSearchComments(true); break;
case "browseFiles" : core.getMuOptions().setBrowseFiles(true); break;
case "speedSmoothSeconds" : core.getMuOptions().setSpeedSmoothSeconds(getPositiveInteger(value,"Download speed smoothing interval (second)")); break;
case "inbound.length" : core.getI2pOptions().setProperty(name, String.valueOf(getPositiveInteger(value,"Inbound tunnel length"))); break;
case "inbound.quantity" : core.getI2pOptions().setProperty(name, String.valueOf(getPositiveInteger(value,"Inbound tunnel quantity"))); break;
case "outbound.length" : core.getI2pOptions().setProperty(name, String.valueOf(getPositiveInteger(value,"Outbound tunnel length"))); break;
case "outbound.quantity" : core.getI2pOptions().setProperty(name, String.valueOf(getPositiveInteger(value,"Outbound tunnel quantity"))); break;
case "speedSmoothSeconds" : core.getMuOptions().setSpeedSmoothSeconds(Integer.parseInt(value)); break;
case "inbound.length" : core.getI2pOptions().setProperty(name, value); break;
case "inbound.quantity" : core.getI2pOptions().setProperty(name, value); break;
case "outbound.length" : core.getI2pOptions().setProperty(name, value); break;
case "outbound.quantity" : core.getI2pOptions().setProperty(name, value); break;
case "fileFeed" : core.getMuOptions().setFileFeed(true); break;
case "advertiseFeed" : core.getMuOptions().setAdvertiseFeed(true); break;
case "autoPublishSharedFiles" : core.getMuOptions().setAutoPublishSharedFiles(true); break;
case "defaultFeedAutoDownload" : core.getMuOptions().setDefaultFeedAutoDownload(true); break;
case "defaultFeedSequential" : core.getMuOptions().setDefaultFeedSequential(true); break;
case "defaultFeedUpdateInterval" : core.getMuOptions().setDefaultFeedUpdateInterval(60000 * getPositiveInteger(value,"Feed update frequency (minutes")); break;
case "defaultFeedItemsToKeep" : core.getMuOptions().setDefaultFeedItemsToKeep(getInteger(value, "Number of items to keep on disk (-1 means unlimited)")); break;
case "defaultFeedUpdateInterval" : core.getMuOptions().setDefaultFeedUpdateInterval(60000 * Integer.parseInt(value)); break;
case "defaultFeedItemsToKeep" : core.getMuOptions().setDefaultFeedItemsToKeep(Integer.parseInt(value)); break;
// TODO: ui settings
}
}
private static int getInteger(String s, String fieldName) throws Exception {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
throw new Exception(Util._t("Bad input")+ ": \"" + s + "\" " + Util._t(fieldName));
private interface InputValidator {
void validate(String input) throws Exception;
}
private static class IntegerValidator implements InputValidator {
private final String fieldName;
IntegerValidator(String fieldName) {
this.fieldName = fieldName;
}
public void validate(String input) throws Exception {
try {
Integer.parseInt(input);
} catch (NumberFormatException e) {
throw new Exception(Util._t("Bad input")+ ": \"" + input + "\" " + Util._t(fieldName));
}
}
}
private static int getPositiveInteger(String s, String fieldName) throws Exception {
int rv = getInteger(s, fieldName);
if (rv <= 0)
throw new Exception(Util._t("Bad input")+ ": \"" + s + "\" " + Util._t(fieldName));
return rv;
private static class PositiveIntegerValidator implements InputValidator {
private final String fieldName;
PositiveIntegerValidator(String fieldName) {
this.fieldName = fieldName;
}
public void validate(String input) throws Exception {
try {
int value = Integer.parseInt(input);
if (value <= 0)
throw new Exception(Util._t("Bad input") + " : \"" + Util._t(fieldName) + "\" " + Util._t("must be greater than zero"));
} catch (NumberFormatException e) {
throw new Exception(Util._t("Bad input")+ ": \"" + input + "\" " + Util._t(fieldName));
}
}
}
private static class DirectoryValidator implements InputValidator {
public void validate(String input) throws Exception {
File f = new File(input);
f = f.getCanonicalFile();
if (!f.exists())
throw new Exception(Util._t("Bad input") + " : " + Util._t("{0} does not exist",input));
if (!f.isDirectory())
throw new Exception(Util._t("Bad input") + " : " + Util._t("{0} is not a directory",input));
if (!f.canWrite())
throw new Exception(Util._t("Bad input") + " : " + Util._t("{0} not writeable",input));
}
}
private static File getDirectory(String s) throws Exception {
File f = new File(s);
f = f.getCanonicalFile();
if (!f.exists())
throw new Exception(Util._t("Bad input") + " : " + Util._t("{0} does not exist",s));
if (!f.isDirectory())
throw new Exception(Util._t("Bad input") + " : " + Util._t("{0} is not a directory",s));
if (!f.canWrite())
throw new Exception(Util._t("Bad input") + " : " + Util._t("{0} not writeable",s));
return f;
return f.getCanonicalFile();
}
@Override

View File

@ -81,6 +81,7 @@ public class Util {
_x("Mark Neutral"),
_x("Mark Trusted"),
_x("MuWire Status"),
_x("must be greater than zero"),
_x("Name"),
_x("Number of items to keep on disk (-1 means unlimited)"),
_x("Outgoing Connections"),