return this.set(conf, sid, opt, undefined);
},
+ get_first: function(conf, type, opt)
+ {
+ var sid = undefined;
+
+ L.uci.sections(conf, type, function(s) {
+ if (typeof(sid) != 'string')
+ sid = s['.name'];
+ });
+
+ return this.get(conf, sid, opt);
+ },
+
+ set_first: function(conf, type, opt, val)
+ {
+ var sid = undefined;
+
+ L.uci.sections(conf, type, function(s) {
+ if (typeof(sid) != 'string')
+ sid = s['.name'];
+ });
+
+ return this.set(conf, sid, opt, val);
+ },
+
+ unset_first: function(conf, type, opt)
+ {
+ return this.set_first(conf, type, opt, undefined);
+ },
+
_reload: function()
{
var pkgs = [ ];
return dev.getTrafficHistory();
},
+ renderBadge: function()
+ {
+ var badge = $('<span />')
+ .addClass('badge')
+ .text('%s: '.format(this.name()));
+
+ var dev = this.getDevice();
+ var subdevs = this.getSubdevices();
+
+ if (subdevs.length)
+ for (var j = 0; j < subdevs.length; j++)
+ badge.append($('<img />')
+ .attr('src', subdevs[j].icon())
+ .attr('title', '%s (%s)'.format(subdevs[j].description(), subdevs[j].name() || '?')));
+ else if (dev)
+ badge.append($('<img />')
+ .attr('src', dev.icon())
+ .attr('title', '%s (%s)'.format(dev.description(), dev.name() || '?')));
+ else
+ badge.append($('<em />').text(L.tr('(No devices attached)')));
+
+ return badge;
+ },
+
setDevices: function(devs)
{
var dev = this.getPhysdev();
'ipaddr': function()
{
- if (validation.types['ip4addr'].apply(this) ||
- validation.types['ip6addr'].apply(this))
+ if (L.parseIPv4(this) || L.parseIPv6(this))
return true;
validation.i18n('Must be a valid IP address');
'ip4addr': function()
{
- if (this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(\/(\S+))?$/))
- {
- if ((RegExp.$1 >= 0) && (RegExp.$1 <= 255) &&
- (RegExp.$2 >= 0) && (RegExp.$2 <= 255) &&
- (RegExp.$3 >= 0) && (RegExp.$3 <= 255) &&
- (RegExp.$4 >= 0) && (RegExp.$4 <= 255) &&
- ((RegExp.$6.indexOf('.') < 0)
- ? ((RegExp.$6 >= 0) && (RegExp.$6 <= 32))
- : (validation.types['ip4addr'].apply(RegExp.$6))))
- return true;
- }
+ if (L.parseIPv4(this))
+ return true;
validation.i18n('Must be a valid IPv4 address');
return false;
'ip6addr': function()
{
- if (this.match(/^([a-fA-F0-9:.]+)(\/(\d+))?$/))
- {
- if (!RegExp.$2 || ((RegExp.$3 >= 0) && (RegExp.$3 <= 128)))
- {
- var addr = RegExp.$1;
+ if (L.parseIPv6(this))
+ return true;
- if (addr == '::')
- {
- return true;
- }
+ validation.i18n('Must be a valid IPv6 address');
+ return false;
+ },
- if (addr.indexOf('.') > 0)
- {
- var off = addr.lastIndexOf(':');
+ 'netmask4': function()
+ {
+ if (L.isNetmask(L.parseIPv4(this)))
+ return true;
- if (!(off && validation.types['ip4addr'].apply(addr.substr(off+1))))
- {
- validation.i18n('Must be a valid IPv6 address');
- return false;
- }
+ validation.i18n('Must be a valid IPv4 netmask');
+ return false;
+ },
- addr = addr.substr(0, off) + ':0:0';
- }
+ 'netmask6': function()
+ {
+ if (L.isNetmask(L.parseIPv6(this)))
+ return true;
- if (addr.indexOf('::') >= 0)
- {
- var colons = 0;
- var fill = '0';
+ validation.i18n('Must be a valid IPv6 netmask6');
+ return false;
+ },
- for (var i = 1; i < (addr.length-1); i++)
- if (addr.charAt(i) == ':')
- colons++;
+ 'cidr4': function()
+ {
+ if (this.match(/^([0-9.]+)\/(\d{1,2})$/))
+ if (RegExp.$2 <= 32 && L.parseIPv4(RegExp.$1))
+ return true;
- if (colons > 7)
- {
- validation.i18n('Must be a valid IPv6 address');
- return false;
- }
+ validation.i18n('Must be a valid IPv4 prefix');
+ return false;
+ },
- for (var i = 0; i < (7 - colons); i++)
- fill += ':0';
+ 'cidr6': function()
+ {
+ if (this.match(/^([a-fA-F0-9:.]+)\/(\d{1,3})$/))
+ if (RegExp.$2 <= 128 && L.parseIPv6(RegExp.$1))
+ return true;
- if (addr.match(/^(.*?)::(.*?)$/))
- addr = (RegExp.$1 ? RegExp.$1 + ':' : '') + fill +
- (RegExp.$2 ? ':' + RegExp.$2 : '');
- }
+ validation.i18n('Must be a valid IPv6 prefix');
+ return false;
+ },
- if (addr.match(/^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/) != null)
- return true;
+ 'ipmask4': function()
+ {
+ if (this.match(/^([0-9.]+)\/([0-9.]+)$/))
+ {
+ var addr = RegExp.$1, mask = RegExp.$2;
+ if (L.parseIPv4(addr) && L.isNetmask(L.parseIPv4(mask)))
+ return true;
+ }
- validation.i18n('Must be a valid IPv6 address');
- return false;
- }
+ validation.i18n('Must be a valid IPv4 address/netmask pair');
+ return false;
+ },
+
+ 'ipmask6': function()
+ {
+ if (this.match(/^([a-fA-F0-9:.]+)\/([a-fA-F0-9:.]+)$/))
+ {
+ var addr = RegExp.$1, mask = RegExp.$2;
+ if (L.parseIPv6(addr) && L.isNetmask(L.parseIPv6(mask)))
+ return true;
}
- validation.i18n('Must be a valid IPv6 address');
+ validation.i18n('Must be a valid IPv6 address/netmask pair');
return false;
},
if (typeof(a) != typeof(b))
return true;
- if (typeof(a) == 'object')
+ if ($.isArray(a))
{
if (a.length != b.length)
return true;
return false;
}
+ else if ($.isPlainObject(a))
+ {
+ for (var k in a)
+ if (!(k in b))
+ return true;
+
+ for (var k in b)
+ if (!(k in a) || a[k] !== b[k])
+ return true;
+
+ return false;
+ }
return (a != b);
},
for (var i = 0; i < interfaces.length; i++)
{
var iface = interfaces[i];
- var badge = $('<span />')
- .addClass('badge')
- .text('%s: '.format(iface.name()));
-
- var dev = iface.getDevice();
- var subdevs = iface.getSubdevices();
-
- if (subdevs.length)
- for (var j = 0; j < subdevs.length; j++)
- badge.append(this._device_icon(subdevs[j]));
- else if (dev)
- badge.append(this._device_icon(dev));
- else
- badge.append($('<em />').text(L.tr('(No devices attached)')));
$('<li />')
.append($('<label />')
.addClass(itype + ' inline')
- .append($('<input />')
+ .append(this.validator(sid, $('<input />')
.attr('name', itype + id)
.attr('type', itype)
.attr('value', iface.name())
- .prop('checked', !!check[iface.name()]))
- .append(badge))
+ .prop('checked', !!check[iface.name()]), true))
+ .append(iface.renderBadge()))
.appendTo(ul);
}
return true;
},
+ sort: function(section1, section2)
+ {
+ return 0;
+ },
+
sections: function(cb)
{
var s1 = L.uci.sections(this.map.uci_package);
if (this.filter(s1[i]))
s2.push(s1[i]);
+ s2.sort(this.sort);
+
if (typeof(cb) == 'function')
for (var i = 0; i < s2.length; i++)
cb.call(this, s2[i]);