java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java | 134
++++++++++
java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java | 63
++++
java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java | 12
java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml | 8
4 files changed, 216 insertions(+), 1 deletion(-)
New commits:
commit d37de0066ae9b10a2c8e919d4c0fa401a6fdeb26
Author: Johannes Renner <jrenner(a)suse.de>
Date: Tue Sep 18 14:17:11 2012 +0200
Validate proxy format on general config page
diff --git a/java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java
b/java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java
new file mode 100644
index 0000000..cff8ad7
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/common/validator/HostPortValidator.java
@@ -0,0 +1,134 @@
+/**
+ * Copyright (c) 2012 Novell
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ *
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.common.validator;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Input validation for host[:port], where the host part can be either an IP address
+ * (IPv4 or IPv6) or a hostname.
+ */
+public class HostPortValidator {
+
+ // Singleton instance
+ private static HostPortValidator instance;
+
+ // Pattern to match IPv6 address in bracket notation
+ private static final Pattern IPV6_BRACKETS =
Pattern.compile("^\\[(.*)\\](:(\\d*))?$");
+
+ // Private constructor
+ private HostPortValidator() {
+ }
+
+ /**
+ * Return the singleton instance of {@link HostPortValidator}.
+ * @return {@link HostPortValidator} instance
+ */
+ public static HostPortValidator getInstance() {
+ if (instance == null) {
+ instance = new HostPortValidator();
+ }
+ return instance;
+ }
+
+ /**
+ * Return true if the given string is a valid host[:port] representation.
+ * @param hostPort
+ * @return true if hostPort represents a valid host and port, else false.
+ */
+ public boolean isValid(String hostPort) {
+ if (hostPort == null || hostPort.isEmpty()) {
+ return false;
+ }
+ String host;
+ String port;
+
+ if (hostPort.startsWith("[")) {
+ // Parse an IPv6 address in bracket notation
+ Matcher matcher = IPV6_BRACKETS.matcher(hostPort);
+ if (!matcher.matches()) {
+ return false;
+ }
+ host = matcher.group(1);
+ port = matcher.group(3);
+ }
+ else {
+ int colonIndex = hostPort.indexOf(':');
+ if (colonIndex != -1 && colonIndex ==
hostPort.lastIndexOf(':')) {
+ // Split into host:port
+ host = hostPort.substring(0, colonIndex);
+ port = hostPort.substring(colonIndex + 1);
+ }
+ else {
+ host = hostPort;
+ port = null;
+ }
+ }
+
+ // Validate host and port separately
+ boolean isValidHost = true;
+ // Validate IP addresses externally (v4 and v6)
+ if (host.replaceAll("[\\d\\.]", "").isEmpty() ||
host.contains(":")) {
+ isValidHost = isValidIP(host);
+ }
+ boolean isValidPort = true;
+ if (port != null) {
+ isValidPort = isValidPort(port);
+ }
+
+ return isValidHost && isValidPort;
+ }
+
+ /**
+ * Validate IP address format for a given string.
+ * @param ipString
+ * @return true if the given string is a valid IP, else false.
+ */
+ private boolean isValidIP(String ipString) {
+ boolean ret = false;
+ if (ipString != null && !ipString.isEmpty()) {
+ try {
+ InetAddress.getByName(ipString);
+ ret = true;
+ }
+ catch (UnknownHostException e) {
+ // Stay silent
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Parse a port number from a given string and validate it.
+ * @param portString
+ * @return true if the given string is a valid port, else false.
+ */
+ private boolean isValidPort(String portString) {
+ boolean ret = false;
+ if (portString != null && !portString.isEmpty()) {
+ try {
+ int port = Integer.parseInt(portString);
+ ret = port >= 0 && port < 65535;
+ }
+ catch (NumberFormatException e) {
+ // Stay silent
+ }
+ }
+ return ret;
+ }
+}
diff --git a/java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java
b/java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java
new file mode 100644
index 0000000..e96bd91
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/common/validator/test/HostPortValidatorTest.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2012 Novell
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ *
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.common.validator.test;
+
+import com.redhat.rhn.common.validator.HostPortValidator;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class for the {@link HostPortValidator}.
+ */
+public class HostPortValidatorTest extends TestCase {
+
+ public void testIPv4() {
+ assertTrue(HostPortValidator.getInstance().isValid("192.168.1.2"));
+
assertTrue(HostPortValidator.getInstance().isValid("192.168.1.2:8888"));
+ assertTrue(HostPortValidator.getInstance().isValid("192.168.1"));
+
+ assertFalse(HostPortValidator.getInstance().isValid("192.168.1.2:"));
+ assertFalse(HostPortValidator.getInstance().isValid("192.168.1.2.3"));
+ assertFalse(HostPortValidator.getInstance().isValid("1200.5.4.3"));
+
assertFalse(HostPortValidator.getInstance().isValid("192.168.2.1:888888"));
+
assertFalse(HostPortValidator.getInstance().isValid("http://192.168.2.1:8888"));
+ }
+
+ public void testIPv6() {
+
assertTrue(HostPortValidator.getInstance().isValid("2001:0db8:85a3:08d3:1319:8a2e:0370:7344"));
+
assertTrue(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]"));
+
assertTrue(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:8888"));
+
assertTrue(HostPortValidator.getInstance().isValid("[2607:f0d0:1002:51::4]:8888"));
+ assertTrue(HostPortValidator.getInstance().isValid("[::1]"));
+ assertTrue(HostPortValidator.getInstance().isValid("[::1]:8888"));
+
+
assertFalse(HostPortValidator.getInstance().isValid("2001:0db8:85a3:08d3:1319:8a2e:0370:7344:8888"));
+
assertFalse(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]]:8888"));
+
assertFalse(HostPortValidator.getInstance().isValid("[2001:0db8:85a3:08d3:1319:8a2e:0370:7344:8888"));
+
assertFalse(HostPortValidator.getInstance().isValid("2001:0db8:85a3:08d3:1319:8a2e:0370:7344]:8888"));
+ assertFalse(HostPortValidator.getInstance().isValid("[::1]:"));
+ assertFalse(HostPortValidator.getInstance().isValid("[]"));
+ }
+
+ public void testHostnames() {
+ assertTrue(HostPortValidator.getInstance().isValid("myproxy"));
+ assertTrue(HostPortValidator.getInstance().isValid("myproxy:8888"));
+
assertTrue(HostPortValidator.getInstance().isValid("proxy.example.com"));
+
assertTrue(HostPortValidator.getInstance().isValid("proxy.example.com:8888"));
+
+
assertFalse(HostPortValidator.getInstance().isValid("http://proxy.example.com"));
+
assertFalse(HostPortValidator.getInstance().isValid("http://proxy.example.com:8888"));
+ }
+}
diff --git
a/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
b/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
index 257d296..5514537 100644
--- a/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/action/satellite/GeneralConfigAction.java
@@ -16,6 +16,7 @@ package com.redhat.rhn.frontend.action.satellite;
import com.redhat.rhn.common.conf.Config;
import com.redhat.rhn.common.conf.ConfigDefaults;
+import com.redhat.rhn.common.validator.HostPortValidator;
import com.redhat.rhn.common.validator.ValidatorError;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.struts.RequestContext;
@@ -212,7 +213,16 @@ public class GeneralConfigAction extends BaseConfigAction {
*/
private ActionErrors validateForm(DynaActionForm form) {
ActionErrors errors = new ActionErrors();
- String email = (String)
form.get(translateFormPropertyName("traceback_mail"));
+
+ // Check if proxy is given as host:port
+ String proxy = (String) form.get(
+ translateFormPropertyName("server.satellite.http_proxy"));
+ HostPortValidator validator = HostPortValidator.getInstance();
+ if (!(proxy.equals("") || validator.isValid(proxy))) {
+ errors.add(ActionMessages.GLOBAL_MESSAGE,
+ new ActionMessage("error.proxy_invalid"));
+ }
+
String password = (String) form.get(
translateFormPropertyName("server.satellite.http_proxy_password"));
String confirmationPassword = (String) form.get(
diff --git a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
index 51512c1..00dd421 100644
--- a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
+++ b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
@@ -1179,6 +1179,14 @@
http://www.oasis-open.org/committees/xliff/documents/xliff-core-1.1.xsd&q...
<context
context-type="sourcefile">com.redhat.rhn.frontend.action.monitoring.notification.AbstractFilterEditAction</context>
</context-group>
</trans-unit>
+
+ <trans-unit id="error.proxy_invalid">
+<source>HTTP proxy needs to be specified as host:port.</source>
+ <context-group name="ctx">
+ <context
context-type="sourcefile">/rhn/admin/config/GeneralConfig</context>
+ </context-group>
+ </trans-unit>
+
<trans-unit id="/rhn/">
<source>That username is already taken; please choose another.</source>
<context-group name="ctx">