diff --git a/README.md b/README.md index 2db4658..5cb1d12 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,12 @@ activity, making it accessible only to users from specified IP addresses. 1. The users with matching ip addresses can view the activity. 5. Save the activity -## TODO -- Behat tests ip validation +## Testing + +Example of valid ip-addresses: +```txt +192.168.1.1,192.2.1.1-255,255.255.255.255,127.0.0.1,10.0.0.1,8.8.8.8,2001:0db8:85a3:0000:0000:8a2e:0370:7334,2001:db8::8a2e:370:7334,::1,::ffff:192.168.1.1,fe80::1ff:fe23:4567:890a +``` ## Security diff --git a/version.php b/version.php index f2e7135..0253440 100644 --- a/version.php +++ b/version.php @@ -27,8 +27,8 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'availability_ipaddress'; -$plugin->version = 2024072001; -$plugin->release = '4.4.1'; +$plugin->version = 2024072003; +$plugin->release = '4.4.2'; $plugin->requires = 2016120500; $plugin->maturity = MATURITY_STABLE; $plugin->supported = [400, 404]; diff --git a/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-debug.js b/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-debug.js index 85e00e6..31749a4 100644 --- a/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-debug.js +++ b/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-debug.js @@ -1,5 +1,20 @@ YUI.add('moodle-availability_ipaddress-form', function (Y, NAME) { +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + /** * Availability ip-address YUI code * @@ -19,6 +34,7 @@ M.availability_ipaddress = M.availability_ipaddress || {}; // Advanced ip-address regex for validating. M.availability_ipaddress.v4 = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]' + '[0-9]|[1-9][0-9]|[0-9])){3}'; + M.availability_ipaddress.v6 = "^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]" + "\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}" + "(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4})" + @@ -31,6 +47,22 @@ M.availability_ipaddress.v6 = "^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)| "((?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}" + "|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(%[0-9a-zA-Z]{1,})?"; +M.availability_ipaddress.ipv4Regex = "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$"; +M.availability_ipaddress.ipv4RangeRegex = "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}-" + + "(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$"; + +M.availability_ipaddress.ipv6Regex = + "^(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:)|([0-9A-Fa-f]{1,4}:){6}(:|[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|" + + "[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:|((:[0-9A-" + + "Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))|([0-9A-Fa-f]{1,4}:){4}((" + + ":[0-9A-Fa-f]{1,4}){1,3}|(:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-" + + "9][0-9]?))|([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|(:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" + + "\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|(:[0-9A-Fa-f]{1,4}){0,4}:((2" + + "5[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}" + + "){1,6}|(:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|:((:[0" + + "-9A-Fa-f]{1,4}){1,7}|(:[0-9A-Fa-f]{1,4}){0,6}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][" + + "0-9]?)))(%.+)?$"; + /** * @class M.availability_ipaddress.form * @extends M.core_availability.plugin @@ -41,11 +73,10 @@ M.availability_ipaddress.form = Y.Object(M.core_availability.plugin); * Initialises this plugin. * * @method initInner - * @param {Array} param Array of objects */ M.availability_ipaddress.form.initInner = function() { "use strict"; - Y.log('M.availability_ipaddress 1.10'); + Y.log('M.availability_ipaddress 1.2'); }; /** @@ -119,49 +150,44 @@ M.availability_ipaddress.form.getNode = function(json) { */ M.availability_ipaddress.validateIpaddress = function(ipaddresses) { 'use strict'; - Y.log(ipaddresses); + ipaddresses = ipaddresses.split(','); - for (var i in ipaddresses) { - // Test normal ip format. - // Strict ipv4 check. - if (new RegExp(/^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/gm) - .test(ipaddresses[i])) { - Y.log('Correct ipv4'); + // Define regex patterns for IPv4, IPv4 range, IPv6, and subnets + + var subnetRegex = new RegExp( + "^(?:" + M.availability_ipaddress.v4 + "\\/(3[0-2]|[12]?[0-9])|(1\\*))|" + + "(?:" + M.availability_ipaddress.v6 + "\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9]))$" + ); + + for (var i = 0; i < ipaddresses.length; i++) { + var ip = ipaddresses[i]; + + if (new RegExp(M.availability_ipaddress.ipv4Regex).test(ip)) { + Y.log('Correct IPv4: ' + ip); continue; } - var ipv4Regex = new RegExp( - '^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)' + - '(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}-' + - '([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$', - 'gm' - ); - - if (ipv4Regex.test(ipaddresses[i])) { - Y.log('Correct ipv4 range.'); + if (new RegExp(M.availability_ipaddress.ipv4RangeRegex).test(ip)) { + Y.log('Correct IPv4 range: ' + ip); continue; } - if (new RegExp(M.availability_ipaddress.v6) - .test(ipaddresses[i])) { - Y.log('Correct ipv6'); + if (new RegExp(M.availability_ipaddress.ipv6Regex).test(ip)) { + Y.log('Correct IPv6: ' + ip); continue; } - // Test subnet with a regex. - if (new RegExp("^(?:".concat(M.availability_ipaddress.v4 + "\\/(3[0-2]|[12]?[0-9])|(1\\*)", ")|(?:") - .concat(M.availability_ipaddress.v6 + "\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])", ")?\\/gm")) - .test(ipaddresses[i])) { - Y.log('Correct subnet'); + if (subnetRegex.test(ip)) { + Y.log('Correct subnet: ' + ip); continue; } - Y.log('Incorrect ip'); + Y.log('Incorrect IP: ' + ip); return false; } - Y.log('Valid ipaddresses'); + Y.log('All IP addresses are valid'); return true; }; diff --git a/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-min.js b/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-min.js index 12f5479..72abd05 100644 --- a/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-min.js +++ b/yui/build/moodle-availability_ipaddress-form/moodle-availability_ipaddress-form-min.js @@ -1 +1 @@ -YUI.add("moodle-availability_ipaddress-form",function(e,d){M.availability_ipaddress=M.availability_ipaddress||{},M.availability_ipaddress.v4="(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}",M.availability_ipaddress.v6="^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,2}|:)|(?:[a-fA-F\\d]{1,4}:){4}(?:(:[a-fA-F\\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,3}|:)|(?:[a-fA-F\\d]{1,4}:){3}(?:(:[a-fA-F\\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,4}|:)|(?:[a-fA-F\\d]{1,4}:){2}(?:(:[a-fA-F\\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,5}|:)|(?:[a-fA-F\\d]{1,4}:){1}(?:(:[a-fA-F\\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,6}|:)|(?::((?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(%[0-9a-zA-Z]{1,})?",M.availability_ipaddress.form=e.Object(M.core_availability.plugin),M.availability_ipaddress.form.initInner=function(){},M.availability_ipaddress.form.getValue=function(d,a){"use strict";d=a.one("input[name="+d+"]").get("value");return M.availability_ipaddress.validateIpaddress(d),d},M.availability_ipaddress.form.getNode=function(d){"use strict";var a,i="ipaddresses"+M.availability_ipaddress.form.instId;return M.availability_ipaddress.form.instId+=1,a="",a+='",i=e.Node.create(''+(a+='')+""),d.ipaddresses!==undefined&&i.one("input[name=ipaddresses]").set("value",d.ipaddresses),M.availability_ipaddress.form.addedEvents||(M.availability_ipaddress.form.addedEvents=!0,e.one(".availability-field").delegate("valuechange",function(){M.core_availability.form.update()},".availability_ipaddress input[name=ipaddresses]")),i},M.availability_ipaddress.validateIpaddress=function(d){"use strict";for(var a in d=d.split(","))if(!(new RegExp(/^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/gm).test(d[a])||new RegExp("^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}-([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$","gm").test(d[a])||new RegExp(M.availability_ipaddress.v6).test(d[a])||new RegExp("^(?:".concat(M.availability_ipaddress.v4+"\\/(3[0-2]|[12]?[0-9])|(1\\*)",")|(?:").concat(M.availability_ipaddress.v6+"\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])",")?\\/gm")).test(d[a])))return!1;return!0},M.availability_ipaddress.form.fillValue=function(d,a){d.ipaddresses=this.getValue("ipaddresses",a)},M.availability_ipaddress.form.fillErrors=function(d,a){"use strict";var i={};this.fillValue(i,a),!1===M.availability_ipaddress.validateIpaddress(i.ipaddresses)&&d.push("availability_ipaddress:error_ipaddress")}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]}); \ No newline at end of file +YUI.add("moodle-availability_ipaddress-form",function(e,a){M.availability_ipaddress=M.availability_ipaddress||{},M.availability_ipaddress.v4="(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}",M.availability_ipaddress.v6="^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,2}|:)|(?:[a-fA-F\\d]{1,4}:){4}(?:(:[a-fA-F\\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,3}|:)|(?:[a-fA-F\\d]{1,4}:){3}(?:(:[a-fA-F\\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,4}|:)|(?:[a-fA-F\\d]{1,4}:){2}(?:(:[a-fA-F\\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,5}|:)|(?:[a-fA-F\\d]{1,4}:){1}(?:(:[a-fA-F\\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4}){1,6}|:)|(?::((?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(%[0-9a-zA-Z]{1,})?",M.availability_ipaddress.ipv4Regex="^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$",M.availability_ipaddress.ipv4RangeRegex="^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}-(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$",M.availability_ipaddress.ipv6Regex="^(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:)|([0-9A-Fa-f]{1,4}:){6}(:|[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))|([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|(:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|(:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|(:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|(:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|:((:[0-9A-Fa-f]{1,4}){1,7}|(:[0-9A-Fa-f]{1,4}){0,6}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))(%.+)?$",M.availability_ipaddress.form=e.Object(M.core_availability.plugin),M.availability_ipaddress.form.initInner=function(){},M.availability_ipaddress.form.getValue=function(a,d){"use strict";a=d.one("input[name="+a+"]").get("value");return M.availability_ipaddress.validateIpaddress(a),a},M.availability_ipaddress.form.getNode=function(a){"use strict";var d,i="ipaddresses"+M.availability_ipaddress.form.instId;return M.availability_ipaddress.form.instId+=1,d="",d+='",i=e.Node.create(''+(d+='')+""),a.ipaddresses!==undefined&&i.one("input[name=ipaddresses]").set("value",a.ipaddresses),M.availability_ipaddress.form.addedEvents||(M.availability_ipaddress.form.addedEvents=!0,e.one(".availability-field").delegate("valuechange",function(){M.core_availability.form.update()},".availability_ipaddress input[name=ipaddresses]")),i},M.availability_ipaddress.validateIpaddress=function(a){"use strict";var d,i,e;for(a=a.split(","),d=new RegExp("^(?:"+M.availability_ipaddress.v4+"\\/(3[0-2]|[12]?[0-9])|(1\\*))|(?:"+M.availability_ipaddress.v6+"\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9]))$"),i=0;i. + /** * Availability ip-address YUI code * @@ -19,6 +34,7 @@ M.availability_ipaddress = M.availability_ipaddress || {}; // Advanced ip-address regex for validating. M.availability_ipaddress.v4 = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]' + '[0-9]|[1-9][0-9]|[0-9])){3}'; + M.availability_ipaddress.v6 = "^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]" + "\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}" + "(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4})" + @@ -31,6 +47,22 @@ M.availability_ipaddress.v6 = "^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)| "((?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}" + "|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(%[0-9a-zA-Z]{1,})?"; +M.availability_ipaddress.ipv4Regex = "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$"; +M.availability_ipaddress.ipv4RangeRegex = "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}-" + + "(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$"; + +M.availability_ipaddress.ipv6Regex = + "^(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:)|([0-9A-Fa-f]{1,4}:){6}(:|[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|" + + "[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:|((:[0-9A-" + + "Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))|([0-9A-Fa-f]{1,4}:){4}((" + + ":[0-9A-Fa-f]{1,4}){1,3}|(:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-" + + "9][0-9]?))|([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|(:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" + + "\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|(:[0-9A-Fa-f]{1,4}){0,4}:((2" + + "5[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}" + + "){1,6}|(:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|:((:[0" + + "-9A-Fa-f]{1,4}){1,7}|(:[0-9A-Fa-f]{1,4}){0,6}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][" + + "0-9]?)))(%.+)?$"; + /** * @class M.availability_ipaddress.form * @extends M.core_availability.plugin @@ -41,7 +73,6 @@ M.availability_ipaddress.form = Y.Object(M.core_availability.plugin); * Initialises this plugin. * * @method initInner - * @param {Array} param Array of objects */ M.availability_ipaddress.form.initInner = function() { "use strict"; @@ -116,36 +147,32 @@ M.availability_ipaddress.form.getNode = function(json) { */ M.availability_ipaddress.validateIpaddress = function(ipaddresses) { 'use strict'; + ipaddresses = ipaddresses.split(','); - for (var i in ipaddresses) { - // Test normal ip format. - // Strict ipv4 check. - if (new RegExp(/^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/gm) - .test(ipaddresses[i])) { + // Define regex patterns for IPv4, IPv4 range, IPv6, and subnets + + var subnetRegex = new RegExp( + "^(?:" + M.availability_ipaddress.v4 + "\\/(3[0-2]|[12]?[0-9])|(1\\*))|" + + "(?:" + M.availability_ipaddress.v6 + "\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9]))$" + ); + + for (var i = 0; i < ipaddresses.length; i++) { + var ip = ipaddresses[i]; + + if (new RegExp(M.availability_ipaddress.ipv4Regex).test(ip)) { continue; } - var ipv4Regex = new RegExp( - '^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)' + - '(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}-' + - '([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$', - 'gm' - ); - - if (ipv4Regex.test(ipaddresses[i])) { + if (new RegExp(M.availability_ipaddress.ipv4RangeRegex).test(ip)) { continue; } - if (new RegExp(M.availability_ipaddress.v6) - .test(ipaddresses[i])) { + if (new RegExp(M.availability_ipaddress.ipv6Regex).test(ip)) { continue; } - // Test subnet with a regex. - if (new RegExp("^(?:".concat(M.availability_ipaddress.v4 + "\\/(3[0-2]|[12]?[0-9])|(1\\*)", ")|(?:") - .concat(M.availability_ipaddress.v6 + "\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])", ")?\\/gm")) - .test(ipaddresses[i])) { + if (subnetRegex.test(ip)) { continue; } diff --git a/yui/src/form/js/form.js b/yui/src/form/js/form.js index 7032a25..1f27d9b 100644 --- a/yui/src/form/js/form.js +++ b/yui/src/form/js/form.js @@ -1,3 +1,18 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + /** * Availability ip-address YUI code * @@ -17,6 +32,7 @@ M.availability_ipaddress = M.availability_ipaddress || {}; // Advanced ip-address regex for validating. M.availability_ipaddress.v4 = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]' + '[0-9]|[1-9][0-9]|[0-9])){3}'; + M.availability_ipaddress.v6 = "^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]" + "\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}" + "(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(:[a-fA-F\\d]{1,4})" + @@ -29,6 +45,22 @@ M.availability_ipaddress.v6 = "^((?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)| "((?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}" + "|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(%[0-9a-zA-Z]{1,})?"; +M.availability_ipaddress.ipv4Regex = "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$"; +M.availability_ipaddress.ipv4RangeRegex = "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}-" + + "(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$"; + +M.availability_ipaddress.ipv6Regex = + "^(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:)|([0-9A-Fa-f]{1,4}:){6}(:|[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|" + + "[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:|((:[0-9A-" + + "Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))|([0-9A-Fa-f]{1,4}:){4}((" + + ":[0-9A-Fa-f]{1,4}){1,3}|(:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-" + + "9][0-9]?))|([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|(:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" + + "\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|(:[0-9A-Fa-f]{1,4}){0,4}:((2" + + "5[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}" + + "){1,6}|(:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|:((:[0" + + "-9A-Fa-f]{1,4}){1,7}|(:[0-9A-Fa-f]{1,4}){0,6}:((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][" + + "0-9]?)))(%.+)?$"; + /** * @class M.availability_ipaddress.form * @extends M.core_availability.plugin @@ -39,11 +71,10 @@ M.availability_ipaddress.form = Y.Object(M.core_availability.plugin); * Initialises this plugin. * * @method initInner - * @param {Array} param Array of objects */ M.availability_ipaddress.form.initInner = function() { "use strict"; - Y.log('M.availability_ipaddress 1.10'); + Y.log('M.availability_ipaddress 1.2'); }; /** @@ -117,49 +148,44 @@ M.availability_ipaddress.form.getNode = function(json) { */ M.availability_ipaddress.validateIpaddress = function(ipaddresses) { 'use strict'; - Y.log(ipaddresses); + ipaddresses = ipaddresses.split(','); - for (var i in ipaddresses) { - // Test normal ip format. - // Strict ipv4 check. - if (new RegExp(/^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/gm) - .test(ipaddresses[i])) { - Y.log('Correct ipv4'); + // Define regex patterns for IPv4, IPv4 range, IPv6, and subnets + + var subnetRegex = new RegExp( + "^(?:" + M.availability_ipaddress.v4 + "\\/(3[0-2]|[12]?[0-9])|(1\\*))|" + + "(?:" + M.availability_ipaddress.v6 + "\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9]))$" + ); + + for (var i = 0; i < ipaddresses.length; i++) { + var ip = ipaddresses[i]; + + if (new RegExp(M.availability_ipaddress.ipv4Regex).test(ip)) { + Y.log('Correct IPv4: ' + ip); continue; } - var ipv4Regex = new RegExp( - '^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)' + - '(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}-' + - '([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$', - 'gm' - ); - - if (ipv4Regex.test(ipaddresses[i])) { - Y.log('Correct ipv4 range.'); + if (new RegExp(M.availability_ipaddress.ipv4RangeRegex).test(ip)) { + Y.log('Correct IPv4 range: ' + ip); continue; } - if (new RegExp(M.availability_ipaddress.v6) - .test(ipaddresses[i])) { - Y.log('Correct ipv6'); + if (new RegExp(M.availability_ipaddress.ipv6Regex).test(ip)) { + Y.log('Correct IPv6: ' + ip); continue; } - // Test subnet with a regex. - if (new RegExp("^(?:".concat(M.availability_ipaddress.v4 + "\\/(3[0-2]|[12]?[0-9])|(1\\*)", ")|(?:") - .concat(M.availability_ipaddress.v6 + "\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])", ")?\\/gm")) - .test(ipaddresses[i])) { - Y.log('Correct subnet'); + if (subnetRegex.test(ip)) { + Y.log('Correct subnet: ' + ip); continue; } - Y.log('Incorrect ip'); + Y.log('Incorrect IP: ' + ip); return false; } - Y.log('Valid ipaddresses'); + Y.log('All IP addresses are valid'); return true; };