1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML
4.0//EN'
>
4 Copyright (C) 2006-2010 Jonathan Zarate
5 http://www.polarcloud.com/tomato/
7 For use with Tomato Firmware only.
8 No part of this file may be used without permission.
12 <meta http-equiv='content-type' content='text/html;charset=utf-
8'
>
13 <meta name='robots' content='noindex,nofollow'
>
14 <title>[<%
ident(); %>] Edit Access Restrictions
</title>
15 <link rel='stylesheet' type='text/css' href='tomato.css'
>
16 <link rel='stylesheet' type='text/css' href='color.css'
>
17 <script type='text/javascript' src='tomato.js'
></script>
18 <script type='text/javascript' src='protocols.js'
></script>
22 <style type='text/css'
>
26 #res-bp-grid .box1
, #res-bp-grid
.box2
{
62 <script type='text/javascript' src='debug.js'
></script>
64 <script type='text/javascript'
>
65 // <% nvram(''); %> // http_id
67 // {enable}|{begin_mins}|{end_mins}|{dow}|{comp[<comp]}|{rules<rules[...]>}|{http[ ...]}|{http_file}|{desc}
69 if ((rule
= rrule
.match(/^(\d+)\|(-?\d+)\|(-?\d+)\|(\d+)\|(.*?)\|(.*?)\|([^|]*?)\|(\d+)\|(.*)$/m)) == null) {
70 rule
= ['', 1, 1380, 240, 31, '', '', '', 0, 'New Rule ' + (rruleN
+ 1)];
79 for (i
= 0; i
< layer7
.length
; ++i
)
80 layer7
[i
] = [layer7
[i
],layer7
[i
]];
81 layer7
.unshift(['', 'Layer 7 (disabled)']);
84 [0,'IPP2P (disabled)'],[0xFFFF,'All IPP2P Filters'],[1,'AppleJuice'],[2,'Ares'],[4,'BitTorrent'],[8,'Direct Connect'],
85 [16,'eDonkey'],[32,'Gnutella'],[64,'Kazaa'],[128,'Mute'],
87 [4096,'PPLive/UUSee'],
89 [256,'SoulSeek'],[512,'Waste'],[1024,'WinMX'],[2048,'XDCC']
91 ,[8192,'Xunlei/QQCyclone']
95 var dowNames
= ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
99 var cg
= new TomatoGrid();
101 cg
.verifyFields = function(row
, quiet
) {
102 var f
= fields
.getAll(row
)[0];
103 if (v_mac(f
, true)) return true;
104 if (_v_iptaddr(f
, true, false, true, true)) return true;
106 ferror
.set(f
, 'Invalid MAC address or IP address/range', quiet
);
110 cg
.setup = function() {
113 this.init('res-comp-grid', 'sort', 140, [ { type
: 'text', maxlen
: 32 } ] );
114 this.headerSet(['MAC / IP Address']);
115 this.showNewEditor();
116 this.resetNewEditor();
118 if (rule
[5] == '~') return; // wireless disable rule
122 a
= rule
[5].split('>');
123 for (i
= 0; i
< a
.length
; ++i
) {
124 if (!a
[i
].length
) continue;
129 cg
.insertData(-1, [a
[i
]]);
136 a
.value
= ex
? 2 : 1;
144 var bpg
= new TomatoGrid();
146 bpg
.verifyFields = function(row
, quiet
) {
147 var f
= fields
.getAll(row
);
149 this.enDiFields(row
);
151 if ((f
[5].selectedIndex
!= 0) && ((!v_length(f
[6], quiet
, 1)) || (!_v_iptaddr(f
[6], quiet
, false, true, true)))) return 0;
152 if ((f
[1].selectedIndex
!= 0) && (!v_iptport(f
[2], quiet
))) return 0;
154 if ((f
[1].selectedIndex
== 0) && (f
[3].selectedIndex
== 0) && (f
[4].selectedIndex
== 0) && (f
[5].selectedIndex
== 0)) {
155 var m
= 'Please enter a specific address or port, or select an application match';
156 ferror
.set(f
[3], m
, 1);
157 ferror
.set(f
[4], m
, 1);
158 ferror
.set(f
[5], m
, 1);
159 ferror
.set(f
[1], m
, quiet
);
171 bpg
.dataToView = function(data
) {
175 if (data
[5] != 0) s
= ((data
[5] == 1) ? 'To ' : 'From ') + data
[6] + ', ';
177 if (data
[0] <= -2) s
+= (s
.length
? 'a' : 'A') + 'ny protocol';
178 else if (data
[0] == -1) s
+= 'TCP/UDP';
179 else if (data
[0] >= 0) s
+= protocols
[data
[0]] || data
[0];
182 if (data
[1] == 'd') s
+= ', dst port ';
183 else if (data
[1] == 's') s
+= ', src port ';
184 else if (data
[1] == 'x') s
+= ', port ';
185 else s
+= ', all ports';
186 if (data
[1] != 'a') s
+= data
[2].replace(/:/g
, '-');
190 for (i
= 0; i
< ipp2p
.length
; ++i
) {
191 if (data
[3] == ipp2p
[i
][0]) {
192 s
+= ', IPP2P: ' + ipp2p
[i
][1];
197 else if (data
[4] != '') {
198 s
+= ', L7: ' + data
[4];
204 bpg
.fieldValuesToData = function(row
) {
205 var f
= fields
.getAll(row
);
206 return [f
[0].value
, f
[1].value
, (f
[1].selectedIndex
== 0) ? '' : f
[2].value
, f
[3].value
, f
[4].value
, f
[5].value
, (f
[5].selectedIndex
== 0) ? '' : f
[6].value
];
209 bpg
.resetNewEditor = function() {
210 var f
= fields
.getAll(this.newEditor
);
211 f
[0].selectedIndex
= 0;
212 f
[1].selectedIndex
= 0;
214 f
[3].selectedIndex
= 0;
215 f
[4].selectedIndex
= 0;
216 f
[5].selectedIndex
= 0;
218 this.enDiFields(this.newEditor
);
219 ferror
.clearAll(fields
.getAll(this.newEditor
));
222 bpg
._createEditor
= bpg
.createEditor
;
223 bpg
.createEditor = function(which
, rowIndex
, source
) {
224 var row
= this._createEditor(which
, rowIndex
, source
);
225 if (which
== 'edit') this.enDiFields(row
);
229 bpg
.enDiFields = function(row
) {
231 var f
= fields
.getAll(row
);
234 x
= ((x
!= -1) && (x
!= 6) && (x
!= 17));
236 if (f
[1].selectedIndex
== 0) x
= 1;
238 f
[3].disabled
= (f
[4].selectedIndex
!= 0);
239 f
[4].disabled
= (f
[3].selectedIndex
!= 0);
240 f
[6].disabled
= (f
[5].selectedIndex
== 0);
243 bpg
.setup = function() {
244 var a
, i
, r
, count
, protos
;
246 protos
= [[-2, 'Any Protocol'],[-1,'TCP/UDP'],[6,'TCP'],[17,'UDP']];
247 for (i
= 0; i
< 256; ++i
) {
248 if ((i
!= 6) && (i
!= 17)) protos
.push([i
, protocols
[i
] || i
]);
251 this.init('res-bp-grid', 'sort', 140, [ { multi
: [
252 { type
: 'select', prefix
: '<div class="box1">', suffix
: '</div>', options
: protos
},
253 { type
: 'select', prefix
: '<div class="box2">', suffix
: '</div>',
254 options
: [['a','Any Port'],['d','Dst Port'],['s','Src Port'],['x','Src or Dst']] },
255 { type
: 'text', prefix
: '<div class="box3">', suffix
: '</div>', maxlen
: 32 },
256 { type
: 'select', prefix
: '<div class="box4">', suffix
: '</div>', options
: ipp2p
},
257 { type
: 'select', prefix
: '<div class="box5">', suffix
: '</div>', options
: layer7
},
258 { type
: 'select', prefix
: '<div class="box6">', suffix
: '</div>',
259 options
: [[0,'Any Address'],[1,'Dst IP'],[2,'Src IP']] },
260 { type
: 'text', prefix
: '<div class="box7">', suffix
: '</div>', maxlen
: 64 }
262 this.headerSet(['Rules']);
263 this.showNewEditor();
264 this.resetNewEditor();
267 // ---- proto<dir<port<ipp2p<layer7[<addr_type<addr]
269 a
= rule
[6].split('>');
270 for (i
= 0; i
< a
.length
; ++i
) {
273 // ---- fixup for backward compatibility
278 r
[2] = r
[2].replace(/:/g
, '-');
279 this.insertData(-1, r
);
288 function verifyFields(focused
, quiet
)
294 elem
.display(PR('_f_sched_begin'), !E('_f_sched_allday').checked
);
295 elem
.display(PR('_f_sched_sun'), !E('_f_sched_everyday').checked
);
297 b
= E('rt_norm').checked
;
298 elem
.display(PR('_f_comp_all'), PR('_f_block_all'), b
);
300 elem
.display(PR('res-comp-grid'), b
&& E('_f_comp_all').value
!= 0);
301 elem
.display(PR('res-bp-grid'), PR('_f_block_http'), PR('_f_activex'), b
&& !E('_f_block_all').checked
);
303 ferror
.clear('_f_comp_all');
305 e
= E('_f_block_http');
306 e
.value
= e
.value
.replace(/[|"']/g, ' ');
307 if (!v_length(e
, quiet
, 0, 2048 - 16)) return 0;
310 e
.value
= e
.value
.replace(/\|/g, '_');
311 if (!v_length(e
, quiet
, 1)) return 0;
316 function cancelRule()
318 document
.location
= 'restrict.asp';
321 function removeRule()
323 if (!confirm('Delete this rule?')) return;
325 E('delete-button').disabled
= 1;
328 e
.name
= 'rrule' + rruleN
;
335 if (!verifyFields(null, false)) return;
336 if ((cg
.isEditing()) || (bpg
.isEditing())) return;
338 var a
, b
, e
, s
, n
, data
;
341 data
.push(E('_f_enabled').checked
? '1' : '0');
342 if (E('_f_sched_allday').checked
) data
.push(-1, -1);
343 else data
.push(E('_f_sched_begin').value
, E('_f_sched_end').value
);
345 if (E('_f_sched_everyday').checked
) {
350 for (i
= 0; i
< 7; ++i
) {
351 if (E('_f_sched_' + dowNames
[i
].toLowerCase()).checked
) n
|= (1 << i
);
353 if (n
== 0) n
= 0x7F;
357 if (E('rt_norm').checked
) {
358 e
= E('_f_comp_all');
362 ferror
.set(e
, 'No MAC or IP address was specified', 0);
365 if (e
.value
== 2) a
.unshift('!');
366 data
.push(a
.join('>'));
372 if (E('_f_block_all').checked
) {
373 data
.push('', '', '0');
377 a
= bpg
.getAllData();
380 for (i
= 0; i
< a
.length
; ++i
) {
381 a
[i
][2] = a
[i
][2].replace(/-/g
, ':');
382 b
.push(a
[i
].join('<'));
384 data
.push(b
.join('>'));
386 a
= E('_f_block_http').value
.replace(/\r+/g, ' ').replace(/\n+/g, '\n').replace(/ +/g, ' ').replace(/^\s
+|\s
+$/g
, '');
391 if (E('_f_activex').checked
) n
= 1;
392 if (E('_f_flash').checked
) n
|= 2;
393 if (E('_f_java').checked
) n
|= 4;
396 if (((check
+ n
) == 0) && (data
[0] == 1)) {
397 alert('Please specify what items should be blocked.');
404 data
.push('', '', '', '0');
407 data
.push(E('_f_desc').value
);
408 data
= data
.join('|');
410 if (data
.length
>= 2048) {
411 alert('This rule is too big. Please reduce by ' + (data
.length
- 2048) + ' characters.');
416 e
.name
= 'rrule' + rruleN
;
419 E('delete-button').disabled
= 1;
436 E('_f_block_all').checked
= (count
== 0) && (rule
[7].search(/[^\s\r\n]/) == -1) && (rule
[8] == 0);
437 verifyFields(null, 1);
441 <body onload='init()'
>
442 <form name='_fom' id='_fom' method='post' action='tomato.cgi'
>
443 <table id='container' cellspacing=
0>
444 <tr><td colspan=
2 id='header'
>
445 <div class='title'
>Tomato
</div>
446 <div class='version'
>Version <%
version(); %></div>
448 <tr id='body'
><td id='navi'
><script type='text/javascript'
>navi()</script></td>
450 <div id='ident'
><%
ident(); %></div>
454 <input type='hidden' name='_nextpage' value='restrict.asp'
>
455 <input type='hidden' name='_service' value='restrict-restart'
>
456 <input type='hidden' name='rruleNN' id='_rrule' value=''
>
458 <div class='section-title'
>Access Restriction
</div>
459 <div class='section'
>
460 <script type='text/javascript'
>
461 W('<div style="float:right"><small>'+ 'ID: ' + rruleN
.pad(2) + '</small> </div><br>');
463 for (i
= 0; i
< 1440; i
+= 15) tm
.push([i
, timeString(i
)]);
465 createFieldTable('', [
466 { title
: 'Enabled', name
: 'f_enabled', type
: 'checkbox', value
: rule
[1] == '1' },
467 { title
: 'Description', name
: 'f_desc', type
: 'text', maxlen
: 32, size
: 35, value
: rule
[9] },
468 { title
: 'Schedule', multi
: [
469 { name
: 'f_sched_allday', type
: 'checkbox', suffix
: ' All Day ', value
: (rule
[2] < 0) || (rule
[3] < 0) },
470 { name
: 'f_sched_everyday', type
: 'checkbox', suffix
: ' Everyday', value
: (rule
[4] & 0x7F) == 0x7F } ] },
471 { title
: 'Time', indent
: 2, multi
: [
472 { name
: 'f_sched_begin', type
: 'select', options
: tm
, value
: (rule
[2] < 0) ? 0 : rule
[2], suffix
: ' - ' },
473 { name
: 'f_sched_end', type
: 'select', options
: tm
, value
: (rule
[3] < 0) ? 0 : rule
[3] } ] },
474 { title
: 'Days', indent
: 2, multi
: [
475 { name
: 'f_sched_sun', type
: 'checkbox', suffix
: ' Sun ', value
: (rule
[4] & 1) },
476 { name
: 'f_sched_mon', type
: 'checkbox', suffix
: ' Mon ', value
: (rule
[4] & (1 << 1)) },
477 { name
: 'f_sched_tue', type
: 'checkbox', suffix
: ' Tue ', value
: (rule
[4] & (1 << 2)) },
478 { name
: 'f_sched_wed', type
: 'checkbox', suffix
: ' Wed ', value
: (rule
[4] & (1 << 3)) },
479 { name
: 'f_sched_thu', type
: 'checkbox', suffix
: ' Thu ', value
: (rule
[4] & (1 << 4)) },
480 { name
: 'f_sched_fri', type
: 'checkbox', suffix
: ' Fri ', value
: (rule
[4] & (1 << 5)) },
481 { name
: 'f_sched_sat', type
: 'checkbox', suffix
: ' Sat', value
: (rule
[4] & (1 << 6)) } ] },
482 { title
: 'Type', name
: 'f_type', id
: 'rt_norm', type
: 'radio', suffix
: ' Normal Access Restriction', value
: (rule
[5] != '~') },
483 { title
: '', name
: 'f_type', id
: 'rt_wl', type
: 'radio', suffix
: ' Disable Wireless', value
: (rule
[5] == '~') },
484 { title
: 'Applies To', name
: 'f_comp_all', type
: 'select', options
: [[0,'All Computers / Devices'],[1,'The Following...'],[2,'All Except...']], value
: 0 },
485 { title
: ' ', text
: '<table class="tomato-grid" cellspacing=1 id="res-comp-grid"></table>' },
486 { title
: 'Blocked Resources', name
: 'f_block_all', type
: 'checkbox', suffix
: ' Block All Internet Access', value
: 0 },
487 { title
: 'Port /<br>Application', indent
: 2, text
: '<table class="tomato-grid" cellspacing=1 id="res-bp-grid"></table>' },
488 { title
: 'HTTP Request', indent
: 2, name
: 'f_block_http', type
: 'textarea', value
: rule
[7] },
489 { title
: 'HTTP Requested Files', indent
: 2, multi
: [
490 { name
: 'f_activex', type
: 'checkbox', suffix
: ' ActiveX (ocx, cab) ', value
: (rule
[8] & 1) },
491 { name
: 'f_flash', type
: 'checkbox', suffix
: ' Flash (swf) ', value
: (rule
[8] & 2) },
492 { name
: 'f_java', type
: 'checkbox', suffix
: ' Java (class, jar) ', value
: (rule
[8] & 4) } ] }
500 <tr><td id='footer' colspan=
2>
501 <span id='footer-msg'
></span>
502 <input type='button' value='Delete...' id='delete-button' onclick='removeRule()'
>
504 <input type='button' value='Save' id='save-button' onclick='saveRule()'
>
505 <input type='button' value='Cancel' id='cancel-button' onclick='cancelRule()'
>
510 <script type='text/javascript'
>earlyInit();</script>