Commit 6f455e79 authored by Jan Čermák's avatar Jan Čermák

added server-side IP validation, validators converted to new-style classes,...

added server-side IP validation, validators converted to new-style classes, rewrite of JS IP validation - refs #2986 & refs #2995
parent 12fac06c
......@@ -201,7 +201,8 @@ def config_page_post(page_name):
bottle.redirect(request.fullpath)
except TypeError:
# raised by Validator - could happen when the form is posted with wrong fields
pass
logger.exception("Error when saving form.")
logger.warning("Form not saved.")
return config_page.render(config_pages=config_page_map.display_names(),
active_handler_key=page_name)
......
......@@ -178,14 +178,17 @@ class WanHandler(BaseConfigHandler):
.requires("proto", WAN_STATIC)
wan_main.add_field(Textbox, name="ip6addr", label=_("IPv6 address"),
nuci_path="uci.network.wan.ip6addr",
validators=validators.IPv6(),
required=True)\
.requires("proto", WAN_STATIC)\
.requires("static_ipv6", True)
wan_main.add_field(Textbox, name="ip6gw", label=_("IPv6 gateway"),
validators=validators.IPv6(),
nuci_path="uci.network.wan.ip6gw")\
.requires("proto", WAN_STATIC)\
.requires("static_ipv6", True)
wan_main.add_field(Textbox, name="ip6prefix", label=_("IPv6 prefix"),
validators=validators.IPv6Prefix(),
nuci_path="uci.network.wan.ip6prefix")\
.requires("proto", WAN_STATIC)\
.requires("static_ipv6", True)
......
......@@ -19,8 +19,24 @@ var ForisWizard = {};
ForisWizard.validators = {
ipv4: function(value) {
var re_ipv4 = /^(\d{1,3}\.){3}\d{1,3}$/;
return value.search(re_ipv4) != -1;
var bytes = value.split(".");
if (bytes.length != 4)
return false;
var intRE = /^[0-9]+$/;
for (var i = 0; i < bytes.length; i++) {
// check it's an integer number, not exponential format, hex number etc...
if (!intRE.test(bytes[i]))
return false;
if (bytes[i] < 0 || bytes[i] > 255)
return false;
}
return true;
},
ipv6: function(value) {
return true; // TODO: at least basic IPv6 check
},
ipv6prefix: function(value) {
return true; // TODO: at least basic IPv6 check
},
integer: function(value) {
var re_integer = /^\d+$/;
......
......@@ -21,7 +21,7 @@ import re
PARAM_DELIMITER = "|"
class Validator:
class Validator(object):
js_validator = None
def __deepcopy__(self, memo):
......@@ -42,7 +42,7 @@ class Validator:
class RegExp(Validator):
def __init__(self, msg, reg_exp):
self.reg_exp = re.compile(reg_exp)
Validator.__init__(self, msg, lambda val: bool(self.reg_exp.match(val)))
super(RegExp, self).__init__(msg, lambda val: bool(self.reg_exp.match(val)))
def valid(self, value):
return bool(self.reg_exp.match(value))
......@@ -52,28 +52,73 @@ class NotEmpty(Validator):
js_validator = "notempty"
def __init__(self):
Validator.__init__(self, "This field is required.", bool)
super(NotEmpty, self).__init__("This field is required.", bool)
class IPv4(RegExp):
class IPv4(Validator):
js_validator = "ipv4"
def __init__(self):
RegExp.__init__(self, "Not a valid IPv4 address.", r"(\d{1,3}\.){3}\d{1,3}")
super(IPv4, self).__init__("Not a valid IPv4 address.", None)
def valid(self, value):
import socket
try:
socket.inet_pton(socket.AF_INET, value)
return True
except socket.error:
pass
return False
class IPv6(Validator):
js_validator = "ipv6"
def __init__(self):
super(IPv6, self).__init__("Not a valid IPv6 address.", None)
def valid(self, value):
import socket
try:
socket.inet_pton(socket.AF_INET6, value)
return True
except Exception:
pass
return False
class IPv6Prefix(Validator):
js_validator = "ipv6prefix"
def __init__(self):
super(IPv6Prefix, self).__init__("Not a valid IPv6 prefix.", None)
def valid(self, value):
import socket
try:
address, length = value.split("/")
length = int(length)
socket.inet_pton(socket.AF_INET6, address)
if length < 0 or length > 128:
return False
return True
except Exception:
pass
return False
class Integer(RegExp):
js_validator = "integer"
def __init__(self):
RegExp.__init__(self, "Is not a number.", r"\d+")
super(Integer, self).__init__("Is not a number.", r"\d+")
class MacAddress(RegExp):
js_validator = "macaddress"
def __init__(self):
RegExp.__init__(self, "MAC address is not valid.", r"([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}")
super(MacAddress, self).__init__("MAC address is not valid.", r"([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}")
class InRange(Validator):
......@@ -90,7 +135,7 @@ class LenRange(Validator):
def __init__(self, low, high):
test = lambda val: low <= len(val) <= high
Validator.__init__(self, "Length must be from %s to %s characters." % (low, high), test)
super(LenRange, self).__init__("Length must be from %s to %s characters." % (low, high), test)
self.js_validator_params = "%s%s%s" % (low, PARAM_DELIMITER, high)
......@@ -98,7 +143,7 @@ class FieldsEqual(Validator):
js_validator = "eqfields"
def __init__(self, field1, field2, message):
Validator.__init__(self, message, lambda data: data[field1] == data[field2])
super(FieldsEqual, self).__init__(message, lambda data: data[field1] == data[field2])
self.js_validator_params = PARAM_DELIMITER.join([field1, field2, message])
......
......@@ -332,7 +332,8 @@ def step_post(number=1):
bottle.redirect(reverse("wizard_step", number=int(number) + 1))
except TypeError:
# raised by Validator - could happen when the form is posted with wrong fields
pass
logger.exception("Error when saving form.")
logger.warning("Form not saved.")
return wiz.render(stepnumber=number)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment