├── .gitignore
├── LICENSE
├── README.md
├── handlers.js
├── package.json
├── server.js
└── tpl
├── auth.html
├── client.js
├── favicon.ico
├── img
├── delete.png
├── edit.png
├── lan.png
├── load.png
├── logout.png
├── logs.png
├── make.png
├── portmap.png
├── reset.png
├── save.png
├── settings.png
├── tcpdump.png
├── ui-bg_flat_0_aaaaaa_40x100.png
├── ui-icons_222222_256x240.png
└── ui-icons_454545_256x240.png
├── index.html
├── jquery-ui.css
├── jquery-ui.min.js
├── jquery.min.js
├── styles
├── config.scss
└── style.scss
├── template.js
├── theme
├── DarkGray.css
├── Navajo.css
└── Silver.css
└── tools.js
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/node
3 |
4 | .sass-cache
5 |
6 | ### Node ###
7 | # Logs
8 | logs
9 | *.log
10 | npm-debug.log*
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 |
24 | # nyc test coverage
25 | .nyc_output
26 |
27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
28 | .grunt
29 |
30 | # node-waf configuration
31 | .lock-wscript
32 |
33 | # Compiled binary addons (http://nodejs.org/api/addons.html)
34 | build/Release
35 |
36 | # Dependency directories
37 | node_modules
38 | jspm_packages
39 |
40 | # Optional npm cache directory
41 | .npm
42 |
43 | # Optional eslint cache
44 | .eslintcache
45 |
46 | # Optional REPL history
47 | .node_repl_history
48 |
49 | # Output of 'npm pack'
50 | *.tgz
51 |
52 | # Yarn Integrity file
53 | .yarn-integrity
54 |
55 |
56 | # End of https://www.gitignore.io/api/node
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | iptables WEB gui
2 |
3 | 
4 |
5 | ### Howto install ###
6 |
7 | In first time you need to Download and install Node.js
8 |
9 | ### Howto use ###
10 |
11 | * Clone repository:
12 | ```bash
13 | git clone https://github.com/puux/iptables.git
14 | ```
15 | * Run server:
16 | ```bash
17 | cd iptables
18 | # only for first time you, need to download dependancies
19 | npm install
20 | # and then you can start the server
21 | node server.js
22 | ```
23 | * Open browser and goto http://127.0.0.1:1337/
24 |
25 | ### Howto create own theme ###
26 |
27 | * cd ./tpl/styles/
28 | * open and change config.scss
29 | * compile: scss --sourcemap=none style.scss ../theme/MyTheme.css
30 | * select theme in Settings->Theme
31 |
32 | ### Default user and password ###
33 |
34 | User: admin
35 | Pass: (empty)
36 |
37 | You can change this here https://github.com/puux/iptables/blob/master/handlers.js#L14
38 |
--------------------------------------------------------------------------------
/handlers.js:
--------------------------------------------------------------------------------
1 | var proc = require('child_process');
2 | var fs = require("fs");
3 | var url = require("url");
4 | var querystring = require("querystring");
5 |
6 | module.exports = {
7 |
8 | auth: false,
9 | authUsers: {},
10 |
11 | settingsDir: "/etc/iptables/config.json",
12 | _settings: {
13 | savePath: "/etc/iptables/rules.save",
14 | user: "admin",
15 | pass: "",
16 | theme: "Silver",
17 | themes: []
18 | },
19 |
20 | loadSettings: function() {
21 | fs.exists(this.settingsDir, function(ex){
22 | if(ex) {
23 | fs.readFile(module.exports.settingsDir, [], function(err, data) {
24 | // Restore new settings after load from file
25 | var s = module.exports._settings;
26 | module.exports._settings = JSON.parse(data);
27 | for(var key in s) {
28 | if(!module.exports._settings[key]) {
29 | module.exports._settings[key] = s[key];
30 | }
31 | }
32 | module.exports.auth = module.exports._settings.pass === "";
33 | console.log("Load settings from " + module.exports.settingsDir);
34 | });
35 | }
36 | });
37 | },
38 |
39 | saveSettings: function() {
40 | fs.writeFile(this.settingsDir, JSON.stringify(this._settings), function(err) {
41 | if(err) {
42 | return console.log(err);
43 | }
44 |
45 | console.log("The file was saved!");
46 | });
47 | },
48 |
49 | index: function(req, res) {
50 | fs.readFile('./tpl/index.html', [], function(err, data) {
51 | //res.writeHead(320, {"Content-Type": "text/plain"});
52 | res.end(data);
53 | });
54 | },
55 |
56 | showChannel: function(req, res) {
57 | var query = url.parse(req.url).query;
58 | var args = querystring.parse(query);
59 |
60 | var run = "iptables -t " + args.t + " -S " + args.c.toUpperCase();
61 | proc.exec(run, function(error, stdout, stderr) {
62 | var arr = stdout.split("\n");
63 |
64 | res.end(JSON.stringify(arr));
65 | });
66 | },
67 |
68 | deleteRule: function(req, res) {
69 | var query = url.parse(req.url).query;
70 | var args = querystring.parse(query);
71 |
72 | proc.exec("iptables -t " + args.t + " -D " + args.c.toUpperCase() + " " + args.i, function(error, stdout, stderr) {
73 | module.exports.showChannel(req, res);
74 | });
75 | },
76 |
77 | insertRule: function (req, res) {
78 | var body = '';
79 | req.on('data', function (data) {
80 | body += data;
81 | });
82 | req.on('end', function () {
83 | var post = querystring.parse(body);
84 |
85 | var rule = post['rule'];
86 | console.log(rule);
87 | proc.exec("iptables " + rule, function(error, stdout, stderr) {
88 | if(stderr) {
89 | res.end(stderr);
90 | }
91 | else {
92 | module.exports.showChannel(req, res);
93 | }
94 | });
95 | });
96 | },
97 |
98 | monitor: function(req, res) {
99 | var query = url.parse(req.url).query;
100 | var args = querystring.parse(query);
101 |
102 | var run = "iptables -t " + args.t + " -L " + args.c.toUpperCase() + " -vn";
103 | proc.exec(run, function(error, stdout, stderr) {
104 | var arr = stdout.split("\n");
105 |
106 | res.writeHead(200, {"Cache-Control": "no-cache"});
107 | res.end(JSON.stringify(arr));
108 | });
109 | },
110 |
111 | chainList: function(req, res) {
112 | var new_arr = [];
113 | var n = 0;
114 |
115 | proc.exec("iptables -S", function(error, stdout, stderr) {
116 | var arr = stdout.split("\n");
117 |
118 | var n = 0;
119 | for(var i = 0; i < arr.length; i++) {
120 | var item = arr[i];
121 | if(item.indexOf("-N") === 0) {
122 | new_arr[n++] = item.substring(3) + " (filter)";
123 | }
124 | }
125 |
126 | proc.exec("iptables -t nat -S", function(error, stdout, stderr) {
127 | var arr = stdout.split("\n");
128 |
129 | for(var i = 0; i < arr.length; i++) {
130 | var item = arr[i];
131 | if(item.indexOf("-N") === 0) {
132 | new_arr[n++] = item.substring(3) + " (nat)";
133 | }
134 | }
135 |
136 | proc.exec("iptables -t mangle -S", function(error, stdout, stderr) {
137 | var arr = stdout.split("\n");
138 |
139 | for(var i = 0; i < arr.length; i++) {
140 | var item = arr[i];
141 | if(item.indexOf("-N") === 0) {
142 | new_arr[n++] = item.substring(3) + " (mangle)";
143 | }
144 | }
145 |
146 | res.end(JSON.stringify(new_arr));
147 | });
148 | });
149 | });
150 | },
151 |
152 | save: function(req, res) {
153 | proc.exec("iptables-save > " + module.exports._settings.savePath, function(error, stdout, stderr) {
154 |
155 | res.end(stderr);
156 | });
157 | },
158 |
159 | load: function(req, res) {
160 | proc.exec("iptables-restore < " + module.exports._settings.savePath, function(error, stdout, stderr) {
161 |
162 | res.end(stderr);
163 | });
164 | },
165 |
166 | settings: function(req, res) {
167 | var query = url.parse(req.url).query;
168 | var args = querystring.parse(query);
169 |
170 | if(args.c === "save") {
171 | var body = '';
172 | req.on('data', function (data) {
173 | body += data;
174 | });
175 | req.on('end', function () {
176 | var post = querystring.parse(body);
177 | var data = post['data'];
178 |
179 | module.exports._settings = JSON.parse(data);
180 | module.exports.saveSettings();
181 | });
182 | res.end();
183 | }
184 | else {
185 | var themes = [];
186 | var items = fs.readdirSync("./tpl/theme");
187 | for (var item of items) {
188 | themes.push(item.substring(0, item.length-4));
189 | }
190 | module.exports._settings.themes = themes;
191 | res.end(JSON.stringify(module.exports._settings));
192 | }
193 | },
194 |
195 | authMe: function(req, res) {
196 | var pathname = url.parse(req.url).pathname;
197 |
198 | if(pathname === "/login") {
199 | var body = '';
200 | req.on('data', function (data) {
201 | body += data;
202 | });
203 | req.on('end', function () {
204 | var post = querystring.parse(body);
205 | var login = post['login'];
206 | var pass = post['pass'];
207 |
208 | var auth = login === module.exports._settings.user && pass === module.exports._settings.pass;
209 | if(auth) {
210 | var ip = req.connection.remoteAddress;
211 | module.exports.authUsers[ip] = 1;
212 | res.writeHead(301, {"Location": "/"});
213 | res.end();
214 | }
215 | else {
216 | res.end("Error!");
217 | }
218 | });
219 | }
220 | else {
221 | res.writeHead(301, {"Location": "auth.html", "Cache-Control": "no-cache"});
222 | res.end();
223 | }
224 | },
225 |
226 | isAuth: function(req) {
227 | var ip = req.connection.remoteAddress;
228 | return module.exports.auth || module.exports.authUsers[ip];
229 | },
230 |
231 | logout: function(req, res) {
232 | var ip = req.connection.remoteAddress;
233 | module.exports.authUsers[ip] = 0;
234 | res.writeHead(301, {"Location": "auth.html", "Cache-Control": "no-cache"});
235 | res.end();
236 | },
237 |
238 | userList: function(req, res) {
239 | for(var ip in module.exports.authUsers) {
240 | res.write("IP: " + ip + " " + (module.exports.authUsers[ip] ? "auth" : "none"));
241 | }
242 | res.end();
243 | }
244 | };
245 |
246 | module.exports.loadSettings();
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iptables",
3 | "version": "1.0.0",
4 | "description": "iptables WEB gui ",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server.js"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/puux/iptables.git"
13 | },
14 | "keywords": [
15 | "iptables",
16 | "web",
17 | "gui"
18 | ],
19 | "author": "puux",
20 | "license": "GPL-2.0",
21 | "bugs": {
22 | "url": "https://github.com/puux/iptables/issues"
23 | },
24 | "homepage": "https://github.com/puux/iptables#readme",
25 | "dependencies": {
26 | "nodejs-websocket": "^1.7.1"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 | var handle = require('./handlers');
3 | var url = require("url");
4 | var fs = require("fs");
5 |
6 | var handles = {};
7 | handles["/"] = handle.index;
8 | handles["/channel"] = handle.showChannel;
9 | handles["/delete"] = handle.deleteRule;
10 | handles["/insert"] = handle.insertRule;
11 | handles["/mon"] = handle.monitor;
12 | handles["/save"] = handle.save;
13 | handles["/load"] = handle.load;
14 | handles["/settings"] = handle.settings;
15 | handles["/chainlist"] = handle.chainList;
16 | handles["/login"] = handle.authMe;
17 | handles["/logout"] = handle.logout;
18 | handles["/users"] = handle.userList;
19 |
20 | http.createServer(function handler(req, res) {
21 | var pathname = url.parse(req.url).pathname;
22 |
23 | req.setEncoding("utf8");
24 |
25 | if (handles[pathname]) {
26 | if(handle.isAuth(req)) {
27 | handles[pathname](req, res);
28 | }
29 | else {
30 | handle.authMe(req, res);
31 | }
32 | }
33 | else {
34 | var file = "./tpl" + pathname;
35 |
36 | fs.exists(file, function(ex) {
37 | if(ex) {
38 | fs.readFile(file, [], function(err, data) {
39 | //res.writeHead(320, {"Content-Type": "text/plain"});
40 | res.end(data);
41 | });
42 | }
43 | else {
44 | console.log("No request handler found for " + pathname);
45 | res.writeHead(404, {"Content-Type": "text/plain"});
46 | res.write("404 Not found");
47 | res.end();
48 | }
49 | });
50 | }
51 | }).listen(1337);
52 | console.log('Server running at http://*:1337/');
53 |
54 |
55 | // ------------------ WebSocket ------------------------------------------------
56 | var proc = require('child_process');
57 | var ws = require("nodejs-websocket");
58 | var log = null;
59 | var dump = null;
60 |
61 | function closeLogs() {
62 | if(log) {
63 | log.kill('SIGHUP');
64 | log = null;
65 | }
66 | }
67 |
68 | function closeDump() {
69 | if(dump) {
70 | dump.kill('SIGHUP');
71 | dump = null;
72 | }
73 | }
74 |
75 | var server = ws.createServer(function (conn) {
76 | conn.on("text", function (data) {
77 | var params = JSON.parse(data);
78 | if(params.name == "syslog") {
79 | log = proc.spawn("tail", ["-f", "/var/log/syslog"]);
80 | log.stdout.on('data', function (lines) {
81 | var outData = {name: params.name, data: lines.toString().split("\n")};
82 | if(log)
83 | conn.sendText(JSON.stringify(outData));
84 | });
85 | }
86 | else if(params.name == "dump") {
87 | var args = ["-i", params.eth, "-n", "-l"];
88 | if(params.port)
89 | args.push("port", params.port);
90 | if(params.src)
91 | args.push("src", params.src);
92 | if(params.dst) {
93 | if(params.src)
94 | args.push("or");
95 | args.push("dst", params.dst);
96 | }
97 | conn.sendText(JSON.stringify({name: params.name, data: ["Exec tcpdump with args: " + args.toString()]}));
98 | dump = proc.spawn("tcpdump", args);
99 | dump.stdout.on('data', function (lines) {
100 | var outData = {name: params.name, data: lines.toString().split("\n")};
101 | if(dump)
102 | conn.sendText(JSON.stringify(outData));
103 | });
104 | }
105 | else if(params.name == "closelog") {
106 | closeLogs();
107 | }
108 | else if(params.name == "closedump") {
109 | closeDump();
110 | }
111 | });
112 | conn.on("close", function (code, reason) {
113 | closeLogs();
114 | closeDump();
115 | });
116 | }).listen(8001);
117 |
--------------------------------------------------------------------------------
/tpl/auth.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Login
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/tpl/client.js:
--------------------------------------------------------------------------------
1 | var channel = "";
2 | var table = "";
3 | var webSocket;
4 | var chainPath = [];
5 |
6 | $(document).ready(function(){
7 | rules.showListWithPath("input", "filter");
8 |
9 | $.get("/chainlist", function(data) {
10 | var arr = JSON.parse(data);
11 | $("#customchains").html("");
12 | for(var i = 0; i < arr.length; i++) {
13 | var item = arr[i];
14 | var index = item.indexOf(" ");
15 | var rName = item.substr(0, index);
16 | var rTable = item.substr(index+2, item.length - index - 3);
17 | $("#customchains").append(window.tpl.customChain(rName, rTable));
18 | }
19 | $("#customchains").append(window.tpl.customChainAddNew);
20 | });
21 |
22 | setInterval(rules.monitor, 1000);
23 | tools.selectPage(1);
24 | });
25 |
26 | $(function () {
27 | $('.dropdown').each(function () {
28 | var id = 0;
29 | $(this).parent().eq(0).hoverIntent({
30 | timeout: 100,
31 | over: function () {
32 | var obj = this;
33 | id = setTimeout(function() {
34 | $('.dropdown:eq(0)', obj).slideDown(100);
35 | }, 500);
36 | },
37 | out: function () {
38 | clearTimeout(id);
39 | $('.dropdown:eq(0)', this).fadeOut(200);
40 | }
41 | });
42 | });
43 |
44 | $('.dropdown').each(function(i, it){
45 | var list = $(it).find('li');
46 | if(list.length > 12){
47 | list.parent().addClass('large');
48 | list.each(function(index, item){
49 | if(index >= list.length / 2){
50 | $(item).addClass('second');
51 | }
52 | else{
53 | $(item).addClass('first');
54 | }
55 | });
56 | $(it).find('.first').wrapAll('
');
57 | $(it).find('.second').wrapAll('
');
58 | }
59 | });
60 | });
61 |
62 | var parser = {
63 |
64 | parseChannels: function (data) {
65 |
66 | this.editRuleRow = null;
67 |
68 | var arr = JSON.parse(data);
69 |
70 | $("#main").html('');
71 |
72 | var index = 0;
73 | for(var line in arr) {
74 | var val = arr[line];
75 | if(val) {
76 | $("#main").append(parser.makeRuleTpl(index, val));
77 | }
78 | index++;
79 | }
80 |
81 | $("#main").append('New rule: ');
82 | },
83 |
84 | makeRuleTpl: function (index, text) {
85 | var ntext = this.makeRuleText(text);
86 | return tpl.ruleRow(index, ntext);
87 | },
88 |
89 | FIN_RULES: {DROP:1, ACCEPT:1, LOG:1, TCPMSS:1, RETURN:1, DNAT:1, SNAT:1, MASQUERADE:1, CONNMARK:1, TOS:1, TTL:1},
90 | makeRuleText: function (text) {
91 | text = text
92 | // strings
93 | .replace(/(--log-prefix) "(.*)"/g, function(str, pref, comment){
94 | return pref + ' ";
95 | })
96 | // comment
97 | .replace(/(-m comment --comment) "(.*)" (.*)/g, function(str, param, comment, other){
98 | return other + ' ";
99 | })
100 | .replace(/(-m comment --comment) ([\w]+) (.*)/g, function(str, param, comment, other){
101 | return other + ' ";
102 | })
103 | // network interfaces
104 | .replace(/(-[o|i]) ([a-z0-9]+)/g, function(str, dir, int){
105 | return dir + ' ' + (window._settings.LANS[int] || int) + ' ';
106 | })
107 | // networks
108 | .replace(/(\-d|\-s|\-\-to\-destination) ([0-9\.\/\:]+)/g, '$1 $2 ')
109 | // ports
110 | .replace(/(--dport|--sport) ([0-9\.\/\:]+)/g, function(str, param, port){
111 | return param + ' ' + (window._settings.PORTS[port] || port) + ' ';
112 | })
113 | // rule chain
114 | .replace(/-j (ACCEPT|DROP)($| )/g, '-j $1 $2')
115 | .replace(/-j ([A-Z\_0-9]+)/g, function(str, name) {
116 | var lname = name.toLowerCase();
117 | if(parser.FIN_RULES[name]) {
118 | return "-j " + name;
119 | }
120 | return '-j ' + name + " ";
121 | });
122 |
123 | return text;
124 | },
125 |
126 | editRuleRow: null,
127 | editRuleRowText: "",
128 | editRuleRowIndex: "",
129 | editRuleAction: function (key) {
130 | if(key === 27) {
131 | if(this.editRuleRow) {
132 | this.editRuleRow.html(this.editRuleRowText);
133 | this.endEditRule();
134 | }
135 | }
136 | else if(key === 13) {
137 | this.editRuleRow.html(this.makeRuleText(text = this.editRuleRow.children().val()));
138 | this.endEditRule();
139 | text = text.replace("-A " + channel.toUpperCase(), "-R " + channel.toUpperCase() + " " + this.editRuleRowIndex);
140 | rules.insertText(text);
141 | }
142 | },
143 |
144 | editRule: function (index) {
145 | var rule = $("#rule" + index);
146 | if(this.editRuleRow === null || rule.attr("id") !== this.editRuleRow.attr("id")) {
147 | if(this.editRuleRow) {
148 | this.editRuleRow.html(this.editRuleRowText);
149 | }
150 | var value = rule.text();
151 | this.editRuleRowText = rule.html();
152 | rule.html(' ').children().val(value);
153 | rule.children().focus();
154 |
155 | this.editRuleRow = rule;
156 | this.editRuleRowIndex = index;
157 | }
158 | },
159 |
160 | endEditRule: function() {
161 | this.editRuleRow = null;
162 | }
163 |
164 | };
165 |
166 | var rules = {
167 | showList: function (name, chainTable) {
168 | channel = name;
169 | table = chainTable;
170 |
171 | $(".itemselect").removeClass("itemselect").addClass("item");
172 | $(".item").each(function(index, obj) {
173 | if($(obj).text() === name.toUpperCase()) {
174 | $(obj).removeClass("item").addClass("itemselect");
175 | }
176 | });
177 |
178 | parser.endEditRule();
179 | $.get("channel?c=" + channel + "&t=" + table, parser.parseChannels);
180 | },
181 |
182 | showListWithPath: function (name, chainTable, addPath) {
183 | rules.showList(name, chainTable);
184 |
185 | var obj = {chain: name.toUpperCase(), table: chainTable};
186 | if(addPath) {
187 | chainPath.push(obj);
188 | }
189 | else {
190 | chainPath = [obj];
191 | }
192 |
193 | rules.updatePath();
194 | },
195 |
196 | updatePath: function() {
197 | var code = "";
198 | for(var o of chainPath) {
199 | if(code) code += " / ";
200 | code += '' + o.chain + (code ? "" : "[" + o.table + "]") + " ";
201 | }
202 | tools.setChainPath(code);
203 | },
204 |
205 | showBackPath: function (name) {
206 | var index = 0;
207 | for(var o of chainPath) {
208 | index++;
209 | if(o.chain == name) {
210 | chainPath = chainPath.slice(0, index);
211 | rules.showList(o.chain, o.table);
212 | break;
213 | }
214 | }
215 | rules.updatePath();
216 | },
217 |
218 | remove: function (index) {
219 | $.get("delete?i=" + index + "&c=" + channel + "&t=" + table, parser.parseChannels);
220 | return false;
221 | },
222 |
223 | insert: function () {
224 | this.insertText($("#rule").val());
225 |
226 | return false;
227 | },
228 |
229 | insertText: function (text) {
230 | if(text.search(/-[A|I|R]/g) === -1) {
231 | text = "-A " + channel.toLocaleUpperCase() + " " + text ;
232 | }
233 |
234 | text = "-t " + table + " " + text;
235 |
236 | for(var lan in window._settings.LANS) {
237 | text = text.replace(new RegExp("(-[o|i]) " + window._settings.LANS[lan] + " ", 'g'), function(str, dir, int){
238 | return dir + " " + lan + " ";
239 | });
240 | }
241 | for(var port in window._settings.PORTS) {
242 | text = text.replace(new RegExp("(--dport|--sport) " + window._settings.PORTS[port] + " ", 'g'), function(str, dir, _port){
243 | return dir + " " + port + " ";
244 | });
245 | }
246 |
247 | text = text.replace(/\/\/(.*)/g, '-m comment --comment "$1"');
248 |
249 | $.post("insert?c=" + channel + "&t=" + table, {rule: text}, function(data){
250 | if(data) {
251 | if(data.substr(0, 1) === "[") {
252 | parser.parseChannels(data);
253 | }
254 | else {
255 | showError(data);
256 | }
257 | }
258 | });
259 |
260 | return false;
261 | },
262 |
263 | monitor: function() {
264 | $.get("/mon?c=" + channel + "&t=" + table, function(data){
265 | var arr = JSON.parse(data);
266 | var index = 0;
267 | for(var i = 0; i < arr.length; i++) {
268 | var items = arr[i].trim().replace(/[ ]+/g, ' ').split(" ");
269 |
270 | if(i === 0) {
271 | pkts = 4;
272 | bytes = 6;
273 | }
274 | else {
275 | pkts = 0;
276 | bytes = 1;
277 | }
278 |
279 | $("#pkts" + index).html(items[pkts]);
280 | $("#bytes" + index).html(items[bytes]);
281 | if(i !== 1) {
282 | index++;
283 | }
284 | }
285 | });
286 | },
287 |
288 | addChainName: function(name, _table) {
289 | channel = name;
290 | table = _table;
291 | $.post("insert?c=" + name + "&t=" + table, {rule: "-t " + table + " -N " + name.toUpperCase()}, function(data){
292 | if(data) {
293 | if(data.substr(0, 1) === "[") {
294 | parser.parseChannels(data);
295 | //$(".dropdown").append(window.tpl.customChain(name.toUpperCase()));
296 | $(window.tpl.customChain(name.toUpperCase(), _table)).prependTo(".newchain");
297 | }
298 | else {
299 | showError(data);
300 | }
301 | }
302 | });
303 | },
304 |
305 | addChain: function() {
306 | $(".addchain").dialog({
307 | title:"Create new chain",
308 | modal:true,
309 | resizable:false,
310 | width: 400,
311 | buttons: [
312 | {
313 | text: "Create",
314 | click: function() {
315 | rules.addChainName($("#chainname").val(), $("#chaintable").val());
316 | $(".addchain").dialog("close");
317 | }
318 | }
319 | ]
320 | });
321 | },
322 |
323 | removeChain: function(obj) {
324 | var rName = $(obj).attr("chainname");
325 | var rTable = $(obj).attr("chaintable");
326 |
327 | $.post("insert?t=" + rTable + "&c=" + rName, {rule: "-t " + rTable + " -X " + rName.toUpperCase()}, function(data){
328 | if(data) {
329 | if(data.substr(0, 1) === "[") {
330 | parser.parseChannels(data);
331 | $(obj).parent().parent().remove();
332 | }
333 | else {
334 | showError(data);
335 | }
336 | }
337 | });
338 | },
339 |
340 | resetCounters: function() {
341 | $.post("insert?t=" + table + "&c=" + channel, {rule: "-t " + table + " -Z " + channel.toUpperCase()}, function(data){
342 | if(data) {
343 | if(data.substr(0, 1) === "[") {
344 | parser.parseChannels(data);
345 | }
346 | else {
347 | showError(data);
348 | }
349 | }
350 | });
351 | }
352 | };
353 |
354 | var tools = {
355 | pageIndex: 1,
356 |
357 | save: function() {
358 | $.get("/save", function(data) {
359 | if(data) {
360 | showError(data);
361 | }
362 | else {
363 | showInfo("Save complite!");
364 | }
365 | });
366 | },
367 |
368 | load: function() {
369 | $.get("/load", function(data) {
370 | if(data) {
371 | showError(data);
372 | }
373 | else {
374 | showInfo("Load complite!");
375 | rules.showList(channel, table);
376 | }
377 | });
378 | },
379 |
380 | oldIndex: -1,
381 | selectPage: function(index) {
382 | $("#settings-page" + tools.pageIndex).hide();
383 | tools.pageIndex = index;
384 | $("#settings-page" + index).show();
385 | if(tools.oldIndex !== -1) {
386 | $("#page" + tools.oldIndex).removeClass("itemselected").addClass("item");
387 | }
388 | $("#page" + index).removeClass("item").addClass("itemselected");
389 | tools.oldIndex = index;
390 | },
391 |
392 | addLan: function() {
393 | $("#lans").append(window.tpl.settingsLan("", ""));
394 | },
395 |
396 | removeLan: function(obj) {
397 | $(obj).parent().parent().remove();
398 | },
399 |
400 | addPort: function() {
401 | $("#ports").append(window.tpl.settingsPort("", ""));
402 | },
403 |
404 | settingsDlg: function() {
405 | $(".settings").dialog({
406 | title:"Iptables settings",
407 | modal:true,
408 | resizable:false,
409 | width: 600,
410 | buttons: [
411 | {
412 | text: "Save",
413 | click: function() {
414 | $(".param").each(function(index, obj){
415 | window._settings[obj.id] = $(obj).val();
416 | });
417 | window._settings.LANS = {};
418 | $(".lan").each(function(index, obj){
419 | window._settings.LANS[$(obj).children()[0].firstChild.value] = $(obj).children()[1].firstChild.value;
420 | });
421 | window._settings.PORTS = {};
422 | $(".port").each(function(index, obj){
423 | window._settings.PORTS[$(obj).children()[0].firstChild.value] = $(obj).children()[1].firstChild.value;
424 | });
425 | $.post("/settings?c=save", {data: JSON.stringify(window._settings)}, function(data) {
426 | if(data) {
427 | showError(data);
428 | }
429 | });
430 | $(".settings").dialog("close");
431 |
432 | rules.showList(channel, table);
433 | }
434 | }
435 | ]
436 | });
437 | },
438 |
439 | ruleBuilder: {
440 | new_proto: { def: "none", pref: " -p ", name: "Proto", list: ["none", "TCP", "UDP", "ICMP", "GRE"] },
441 | new_in: { def: "", pref: " -i ", name: "Input", hint: "eth0" },
442 | new_out: { def: "", pref: " -o ", name: "Output", hint: "wlan0" },
443 | new_dest: { def: "", pref: " -d ", name: "Dest", hint: "8.8.0.0/16", pdef: true, sub: { new_dst_port_from: { def: "", pref: " --dport ", name: "from", size: 40, sub: { new_dst_port_to: { def: "", pref: ":", name: "to", size: 40 } } } } },
444 | new_src: { def: "", pref: " -s ", name: "Source", hint: "10.10.0.0/16", pdef: true, sub: { new_src_port_from: { def: "", pref: " --sport ", name: "from", size: 40, sub: { new_src_port_to: { def: "", pref: ":", name: "to", size: 40 } } } } },
445 | new_state: { def: "none", pref: " -m state --state ", name: "State", list: ["none", "NEW", "ESTABLISHED", "RELATED", "INVALID"] },
446 | new_limit: { def: "", pref: " -m limit --limit ", name: "Limit" },
447 | new_action: { def: "", pref: " -j ", name: "Action", list: ["ACCEPT", "DROP", "DNAT", "SNAT", "MARK", "LOG", "MASQUERADE", "MIRROR", "REDIRECT", "RETURN", "TOS", "TTL"],
448 | asvalue: {
449 | DNAT: { new_to_destination: { def: "", pref: " --to-destination ", name: "destination"} },
450 | SNAT: { new_to_source: { def: "", pref: " --to-source ", name: "source"} },
451 | MARK: { new_set_mark: { def: "", pref: " --set-mark ", name: "mark"} },
452 | REDIRECT: { new_to_ports: { def: "", pref: " --to-ports ", name: "to ports"} },
453 | TOS: { new_tos: { def: "", pref: " --set-tos ", name: "tos"} },
454 | TTL: { new_ttl: { def: "", pref: " --ttl-set ", name: "ttl"} },
455 | LOG: {
456 | new_log_prefix: { def: "", pref: " --log-prefix \"", suff: "\"", name: "prefix", size: 60},
457 | new_log_level: { def: "", pref: " --log-level ", name: "level", size: 40}
458 | }
459 | }
460 | }
461 | },
462 |
463 | makeTextField: function(name, rule) {
464 | var value = ' ";
472 | if(rule.sub) {
473 | for(var sub in rule.sub) {
474 | value += " " + rule.sub[sub].name + " " + tools.makeTextField(sub, rule.sub[sub]);
475 | }
476 | }
477 | return value;
478 | },
479 |
480 | addDialogRule: function() {
481 |
482 | var text = "";
483 | for(var rule in tools.ruleBuilder) {
484 | var obj = tools.ruleBuilder[rule];
485 | var value = "";
486 | if(obj.list) {
487 | value = '';
488 | for(var item in obj.list) {
489 | value += '' + obj.list[item] + ' ';
490 | }
491 | value += ' ';
492 | if(obj.asvalue) {
493 | value += ' ';
494 | }
495 | }
496 | else {
497 | value = tools.makeTextField(rule, obj);
498 | }
499 | text += '' + obj.name + ' ' + value + ' ';
500 | }
501 | $("#ruleTable").html(text);
502 |
503 | $("#makeRule").dialog({
504 | title:"Make rule",
505 | modal:true,
506 | resizable:false,
507 | width: 500,
508 | buttons: [
509 | {
510 | text: "Add",
511 | click: function() {
512 | var maker = function(rules) {
513 | var rule = "";
514 | for(var field in rules) {
515 | var obj = rules[field];
516 | var value = $("#" + field).val();
517 | if(value !== obj.def) {
518 | rule += obj.pref + value;
519 | if(obj.suff) {
520 | rule += obj.suff;
521 | }
522 | if(obj.asvalue) {
523 | rule += maker(obj.asvalue[value]);
524 | }
525 | }
526 | if(obj.sub && (obj.pdef || value !== obj.def)) {
527 | rule += maker(obj.sub);
528 | }
529 | }
530 | return rule;
531 | };
532 |
533 | var rule = maker(tools.ruleBuilder);
534 | $("#rule").val(rule);
535 |
536 | $("#makeRule").dialog("close");
537 | }
538 | },
539 | {
540 | text: "Reset",
541 | click: function() {
542 | var reset = function(rules) {
543 | for(var field in rules) {
544 | var obj = rules[field];
545 | $("#" + field).val(obj.def);
546 | if(obj.sub) {
547 | reset(obj.sub);
548 | }
549 | if(obj.asvalue) {
550 | $("#" + field).change();
551 | for(var field2 in obj.asvalue) {
552 | reset(obj.asvalue[field2]);
553 | }
554 | }
555 | }
556 | };
557 | reset(tools.ruleBuilder);
558 | }
559 | }
560 | ]
561 | });
562 | },
563 |
564 | setAction: function(obj) {
565 | var id = obj.id;
566 | if($("#" + id + "_sub").size() !== 0) {
567 | var text = "";
568 | for(var field in tools.ruleBuilder[id].asvalue[$("#" + id).val()]) {
569 | var obj = tools.ruleBuilder[id].asvalue[$("#" + id).val()][field];
570 | text += " " + obj.name + " " + tools.makeTextField(field, obj);
571 | }
572 | $("#" + id + "_sub").html(text);
573 | }
574 | },
575 |
576 | initWS: function(hello) {
577 | if(!webSocket) {
578 | var addr = window.location.toString().substr(7);
579 | addr = addr.substr(0, addr.indexOf(":"));
580 | addr = "ws://" + addr + ":8001";
581 |
582 | webSocket = new WebSocket(addr);
583 | webSocket.onopen = function(event) {
584 | webSocket.send(hello);
585 | };
586 |
587 | webSocket.onmessage = function(event) {
588 | var channel = JSON.parse(event.data);
589 | if(channel.name == "syslog") {
590 | for(var i = 0; i < channel.data.length; i++) {
591 | if(channel.data[i]) {
592 | $("#logs").append('' + channel.data[i] + '
');
593 | }
594 | }
595 | $("#logs").parent().scrollTop(64536);
596 | }
597 | else if(channel.name == "dump") {
598 | for(var i = 0; i < channel.data.length; i++) {
599 | if(channel.data[i]) {
600 | var text = channel.data[i].replace(/IP ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/g, function(str, ip){
601 | return '' + ip + " ";
602 | }).replace(/> ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/g, function(str, ip){
603 | return '> ' + ip + " ";
604 | });
605 | $("#dump").append('' + text + '
');
606 | }
607 | }
608 | $("#dump").scrollTop(64536);
609 | }
610 | };
611 |
612 | webSocket.onclose = function(event) {
613 | webSocket = null;
614 | };
615 | }
616 | else {
617 | webSocket.send(hello);
618 | }
619 | },
620 |
621 | closeWS: function(name){
622 | if(webSocket) {
623 | webSocket.send(name);
624 | }
625 | },
626 |
627 | showLogs: function() {
628 | $("#syslog").dialog({
629 | title:"System logs",
630 | modal:false,
631 | resizable:true,
632 | width: 800,
633 | height: 400
634 | }).on('dialogclose', function(event) {
635 | tools.closeWS(JSON.stringify({name: "closelog"}));
636 | });
637 | tools.initWS(JSON.stringify({name: "syslog"}));
638 | },
639 |
640 | showTCPDump: function() {
641 | $("#tcpdump").dialog({
642 | title:"TCP dump",
643 | modal:false,
644 | resizable:true,
645 | width: 800,
646 | height: 400
647 | }).on('dialogclose', function(event) {
648 | tools.closeWS(JSON.stringify({name: "closedump"}));
649 | $("#dump").html("");
650 | });
651 | },
652 |
653 | dumpParams: function() {
654 | $("#dump").html("");
655 | tools.closeWS(JSON.stringify({name: "closedump"}));
656 | tools.initWS(JSON.stringify({name: "dump", eth: $("#eth").val(), src: $("#src").val(), dst: $("#dst").val(), port: $("#port").val()}));
657 | },
658 |
659 | setChainPath: function(path) {
660 | $("#chainpath").html(path);
661 | }
662 | };
--------------------------------------------------------------------------------
/tpl/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/favicon.ico
--------------------------------------------------------------------------------
/tpl/img/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/delete.png
--------------------------------------------------------------------------------
/tpl/img/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/edit.png
--------------------------------------------------------------------------------
/tpl/img/lan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/lan.png
--------------------------------------------------------------------------------
/tpl/img/load.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/load.png
--------------------------------------------------------------------------------
/tpl/img/logout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/logout.png
--------------------------------------------------------------------------------
/tpl/img/logs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/logs.png
--------------------------------------------------------------------------------
/tpl/img/make.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/make.png
--------------------------------------------------------------------------------
/tpl/img/portmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/portmap.png
--------------------------------------------------------------------------------
/tpl/img/reset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/reset.png
--------------------------------------------------------------------------------
/tpl/img/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/save.png
--------------------------------------------------------------------------------
/tpl/img/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/settings.png
--------------------------------------------------------------------------------
/tpl/img/tcpdump.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/tcpdump.png
--------------------------------------------------------------------------------
/tpl/img/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/tpl/img/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/tpl/img/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/puux/iptables/74b47195a8ba51663e1a6d0eee7f3b37fe580e5e/tpl/img/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/tpl/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | iptables
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | INPUT
29 |
33 |
34 |
35 | OUTPUT
36 |
41 |
42 |
43 | FORWARD
44 |
48 |
49 |
50 | PREROUTING
51 |
55 |
56 |
57 | POSTROUTING
58 |
62 |
63 |
64 | Custom ↓
65 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | ID pkts bytes RULE CMD
76 |
77 |
78 |
79 |
80 |
81 |
82 |
91 |
92 |
93 |
94 |
Global
95 |
Networks map
96 |
Ports map
97 |
98 |
117 |
123 |
129 |
130 |
131 |
139 |
143 |
148 |
167 |
168 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/tpl/jquery-ui.css:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery UI CSS Framework @VERSION
3 | *
4 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5 | * Dual licensed under the MIT or GPL Version 2 licenses.
6 | * http://jquery.org/license
7 | *
8 | * http://docs.jquery.com/UI/Theming/API
9 | */
10 |
11 | /* Layout helpers
12 | ----------------------------------*/
13 | .ui-helper-hidden { display: none; }
14 | .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
16 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
17 | .ui-helper-clearfix { display: inline-block; }
18 | /* required comment for clearfix to work in Opera \*/
19 | * html .ui-helper-clearfix { height:1%; }
20 | .ui-helper-clearfix { display:block; }
21 | /* end clearfix */
22 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
23 |
24 |
25 | /* Interaction Cues
26 | ----------------------------------*/
27 | .ui-state-disabled { cursor: default !important; }
28 |
29 |
30 | /* Icons
31 | ----------------------------------*/
32 |
33 | /* states and images */
34 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
35 |
36 |
37 | /* Misc visuals
38 | ----------------------------------*/
39 |
40 | /* Overlays */
41 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
42 | /*
43 | * jQuery UI Accordion @VERSION
44 | *
45 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
46 | * Dual licensed under the MIT or GPL Version 2 licenses.
47 | * http://jquery.org/license
48 | *
49 | * http://docs.jquery.com/UI/Accordion#theming
50 | */
51 | /* IE/Win - Fix animation bug - #4615 */
52 | .ui-accordion { width: 100%; }
53 | .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
54 | .ui-accordion .ui-accordion-li-fix { display: inline; }
55 | .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
56 | .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
57 | .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
58 | .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
59 | .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
60 | .ui-accordion .ui-accordion-content-active { display: block; }/*
61 | * jQuery UI Autocomplete @VERSION
62 | *
63 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
64 | * Dual licensed under the MIT or GPL Version 2 licenses.
65 | * http://jquery.org/license
66 | *
67 | * http://docs.jquery.com/UI/Autocomplete#theming
68 | */
69 | .ui-autocomplete { position: absolute; cursor: default; }
70 |
71 | /* workarounds */
72 | * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
73 |
74 | /*
75 | * jQuery UI Menu @VERSION
76 | *
77 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
78 | * Dual licensed under the MIT or GPL Version 2 licenses.
79 | * http://jquery.org/license
80 | *
81 | * http://docs.jquery.com/UI/Menu#theming
82 | */
83 | .ui-menu {
84 | list-style:none;
85 | padding: 2px;
86 | margin: 0;
87 | display:block;
88 | float: left;
89 | }
90 | .ui-menu .ui-menu {
91 | margin-top: -3px;
92 | }
93 | .ui-menu .ui-menu-item {
94 | margin:0;
95 | padding: 0;
96 | zoom: 1;
97 | float: left;
98 | clear: left;
99 | width: 100%;
100 | }
101 | .ui-menu .ui-menu-item a {
102 | text-decoration:none;
103 | display:block;
104 | padding:.2em .4em;
105 | line-height:1.5;
106 | zoom:1;
107 | }
108 | .ui-menu .ui-menu-item a.ui-state-hover,
109 | .ui-menu .ui-menu-item a.ui-state-active {
110 | font-weight: normal;
111 | margin: -1px;
112 | }
113 | /*
114 | * jQuery UI Button @VERSION
115 | *
116 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
117 | * Dual licensed under the MIT or GPL Version 2 licenses.
118 | * http://jquery.org/license
119 | *
120 | * http://docs.jquery.com/UI/Button#theming
121 | */
122 | .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
123 | .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
124 | button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
125 | .ui-button-icons-only { width: 3.4em; }
126 | button.ui-button-icons-only { width: 3.7em; }
127 |
128 | /*button text element */
129 | .ui-button .ui-button-text { display: block; line-height: 1.4; }
130 | .ui-button-text-only .ui-button-text { padding: .4em 1em; }
131 | .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
132 | .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
133 | .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
134 | .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
135 | /* no icon support for input elements, provide padding by default */
136 | input.ui-button { padding: .4em 1em; }
137 |
138 | /*button icon element(s) */
139 | .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
140 | .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
141 | .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
142 | .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
143 | .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
144 |
145 | /*button sets*/
146 | .ui-buttonset { margin-right: 7px; }
147 | .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
148 |
149 | /* workarounds */
150 | button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
151 | /*
152 | * jQuery UI Datepicker @VERSION
153 | *
154 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
155 | * Dual licensed under the MIT or GPL Version 2 licenses.
156 | * http://jquery.org/license
157 | *
158 | * http://docs.jquery.com/UI/Datepicker#theming
159 | */
160 | .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
161 | .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
162 | .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
163 | .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
164 | .ui-datepicker .ui-datepicker-prev { left:2px; }
165 | .ui-datepicker .ui-datepicker-next { right:2px; }
166 | .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
167 | .ui-datepicker .ui-datepicker-next-hover { right:1px; }
168 | .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
169 | .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
170 | .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
171 | .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
172 | .ui-datepicker select.ui-datepicker-month,
173 | .ui-datepicker select.ui-datepicker-year { width: 49%;}
174 | .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
175 | .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
176 | .ui-datepicker td { border: 0; padding: 1px; }
177 | .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
178 | .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
179 | .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
180 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
181 |
182 | /* with multiple calendars */
183 | .ui-datepicker.ui-datepicker-multi { width:auto; }
184 | .ui-datepicker-multi .ui-datepicker-group { float:left; }
185 | .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
186 | .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
187 | .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
188 | .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
189 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
190 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
191 | .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
192 | .ui-datepicker-row-break { clear:both; width:100%; }
193 |
194 | /* RTL support */
195 | .ui-datepicker-rtl { direction: rtl; }
196 | .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
197 | .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
198 | .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
199 | .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
200 | .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
201 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
202 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
203 | .ui-datepicker-rtl .ui-datepicker-group { float:right; }
204 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
205 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
206 |
207 | /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
208 | .ui-datepicker-cover {
209 | display: none; /*sorry for IE5*/
210 | display/**/: block; /*sorry for IE5*/
211 | position: absolute; /*must have*/
212 | z-index: -1; /*must have*/
213 | filter: mask(); /*must have*/
214 | top: -4px; /*must have*/
215 | left: -4px; /*must have*/
216 | width: 200px; /*must have*/
217 | height: 200px; /*must have*/
218 | }/*
219 | * jQuery UI Dialog @VERSION
220 | *
221 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
222 | * Dual licensed under the MIT or GPL Version 2 licenses.
223 | * http://jquery.org/license
224 | *
225 | * http://docs.jquery.com/UI/Dialog#theming
226 | */
227 | .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; box-shadow: 5px 5px 10px #000000; }
228 | .ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; }
229 | .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; }
230 | .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
231 | .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
232 | .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
233 | .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
234 | .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
235 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
236 | .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
237 | .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
238 | .ui-draggable .ui-dialog-titlebar { cursor: move; }
239 | /*
240 | * jQuery UI Progressbar @VERSION
241 | *
242 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
243 | * Dual licensed under the MIT or GPL Version 2 licenses.
244 | * http://jquery.org/license
245 | *
246 | * http://docs.jquery.com/UI/Progressbar#theming
247 | */
248 | .ui-progressbar { height:2em; text-align: left; }
249 | .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/*
250 | * jQuery UI Resizable @VERSION
251 | *
252 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
253 | * Dual licensed under the MIT or GPL Version 2 licenses.
254 | * http://jquery.org/license
255 | *
256 | * http://docs.jquery.com/UI/Resizable#theming
257 | */
258 | .ui-resizable { position: relative;}
259 | .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
260 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
261 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
262 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
263 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
264 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
265 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
266 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
267 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
268 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
269 | * jQuery UI Selectable @VERSION
270 | *
271 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
272 | * Dual licensed under the MIT or GPL Version 2 licenses.
273 | * http://jquery.org/license
274 | *
275 | * http://docs.jquery.com/UI/Selectable#theming
276 | */
277 | .ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
278 | /*
279 | * jQuery UI Slider @VERSION
280 | *
281 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
282 | * Dual licensed under the MIT or GPL Version 2 licenses.
283 | * http://jquery.org/license
284 | *
285 | * http://docs.jquery.com/UI/Slider#theming
286 | */
287 | .ui-slider { position: relative; text-align: left; }
288 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
289 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
290 |
291 | .ui-slider-horizontal { height: .8em; }
292 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
293 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
294 | .ui-slider-horizontal .ui-slider-range-min { left: 0; }
295 | .ui-slider-horizontal .ui-slider-range-max { right: 0; }
296 |
297 | .ui-slider-vertical { width: .8em; height: 100px; }
298 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
299 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
300 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
301 | .ui-slider-vertical .ui-slider-range-max { top: 0; }/*
302 | * jQuery UI Tabs @VERSION
303 | *
304 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
305 | * Dual licensed under the MIT or GPL Version 2 licenses.
306 | * http://jquery.org/license
307 | *
308 | * http://docs.jquery.com/UI/Tabs#theming
309 | */
310 | .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
311 | .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
312 | .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
313 | .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
314 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
315 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
316 | .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
317 | .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
318 | .ui-tabs .ui-tabs-hide { display: none !important; }
319 | /*
320 | * jQuery UI CSS Framework @VERSION
321 | *
322 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
323 | * Dual licensed under the MIT or GPL Version 2 licenses.
324 | * http://jquery.org/license
325 | *
326 | * http://docs.jquery.com/UI/Theming/API
327 | *
328 | * To view and modify this theme, visit http://jqueryui.com/themeroller/
329 | */
330 |
331 |
332 | /* Component containers
333 | ----------------------------------*/
334 | .ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
335 | .ui-widget .ui-widget { font-size: 1em; }
336 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
337 | .ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #222/*{bgColorContent}*/; color: white/*{fcContent}*/; }
338 | .ui-widget-content a { color: white/*{fcContent}*/; }
339 | /*.ui-widget-header { border: 1px solid #aaaaaa{borderColorHeader}; background: #cccccc{bgColorHeader} url(img/ui-bg_highlight-soft_75_cccccc_1x100.png){bgImgUrlHeader} 50%{bgHeaderXPos} 50%{bgHeaderYPos} repeat-x{bgHeaderRepeat}; color: black{fcHeader}; font-weight: bold; }*/
340 | .ui-widget-header {
341 | font-weight: bold;
342 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#555), to(#333));
343 | background: -moz-linear-gradient(top, #555, #333);
344 | background-image: -o-linear-gradient(top, #555, #333);
345 | background: -ms-linear-gradient(top, #555, #333);
346 | }
347 | .ui-widget-header a { color: white/*{fcHeader}*/; }
348 |
349 | /* Interaction states
350 | ----------------------------------*/
351 | /*.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3{borderColorDefault}; background: #e6e6e6{bgColorDefault} url(img/ui-bg_glass_75_e6e6e6_1x400.png){bgImgUrlDefault} 50%{bgDefaultXPos} 50%{bgDefaultYPos} repeat-x{bgDefaultRepeat}; font-weight: normal{fwDefault}; color: #555555{fcDefault}; }*/
352 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
353 | border: 1px solid gray; color: white; text-decoration: none; float:right; cursor: pointer; border-radius: 5px;
354 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#333), to(#222));
355 | background: -moz-linear-gradient(top, #333, #222);
356 | background-image: -o-linear-gradient(top, #333, #222);
357 | background: -ms-linear-gradient(top, #333, #222);
358 | border: 1px solid #444;
359 | box-shadow: 0 0 5px #000;
360 | }
361 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
362 | /*.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999{borderColorHover}; background: #dadada{bgColorHover} url(img/ui-bg_glass_75_dadada_1x400.png){bgImgUrlHover} 50%{bgHoverXPos} 50%{bgHoverYPos} repeat-x{bgHoverRepeat}; font-weight: normal{fwDefault}; color: #212121{fcHover}; }*/
363 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {
364 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#333));
365 | background: -moz-linear-gradient(top, #444, #333);
366 | background-image: -o-linear-gradient(top, #444, #333);
367 | background: -ms-linear-gradient(top, #444, #333);
368 | border: 1px solid #444;
369 | box-shadow: 0 0 5px #000;
370 | }
371 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
372 | /*.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa{borderColorActive}; background: #ffffff{bgColorActive} url(img/ui-bg_glass_65_ffffff_1x400.png){bgImgUrlActive} 50%{bgActiveXPos} 50%{bgActiveYPos} repeat-x{bgActiveRepeat}; font-weight: normal{fwDefault}; color: #212121{fcActive}; }*/
373 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {
374 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#333));
375 | background: -moz-linear-gradient(top, #444, #333);
376 | background-image: -o-linear-gradient(top, #444, #333);
377 | background: -ms-linear-gradient(top, #444, #333);
378 | border: 1px solid #444;
379 | box-shadow: 0 0 5px #000;
380 | }
381 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
382 | .ui-widget :active { outline: none; }
383 |
384 | /* Interaction Cues
385 | ----------------------------------*/
386 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(img/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
387 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
388 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(img/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
389 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
390 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
391 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
392 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
393 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
394 |
395 | /* Icons
396 | ----------------------------------*/
397 |
398 | /* states and images */
399 | .ui-icon { width: 16px; height: 16px; background-image: url(img/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
400 | .ui-widget-content .ui-icon {background-image: url(img/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
401 | .ui-widget-header .ui-icon {background-image: url(img/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
402 | .ui-state-default .ui-icon { background-image: url(img/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
403 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(img/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
404 | .ui-state-active .ui-icon {background-image: url(img/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
405 | .ui-state-highlight .ui-icon {background-image: url(img/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
406 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(img/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
407 |
408 | /* positioning */
409 | .ui-icon-carat-1-n { background-position: 0 0; }
410 | .ui-icon-carat-1-ne { background-position: -16px 0; }
411 | .ui-icon-carat-1-e { background-position: -32px 0; }
412 | .ui-icon-carat-1-se { background-position: -48px 0; }
413 | .ui-icon-carat-1-s { background-position: -64px 0; }
414 | .ui-icon-carat-1-sw { background-position: -80px 0; }
415 | .ui-icon-carat-1-w { background-position: -96px 0; }
416 | .ui-icon-carat-1-nw { background-position: -112px 0; }
417 | .ui-icon-carat-2-n-s { background-position: -128px 0; }
418 | .ui-icon-carat-2-e-w { background-position: -144px 0; }
419 | .ui-icon-triangle-1-n { background-position: 0 -16px; }
420 | .ui-icon-triangle-1-ne { background-position: -16px -16px; }
421 | .ui-icon-triangle-1-e { background-position: -32px -16px; }
422 | .ui-icon-triangle-1-se { background-position: -48px -16px; }
423 | .ui-icon-triangle-1-s { background-position: -64px -16px; }
424 | .ui-icon-triangle-1-sw { background-position: -80px -16px; }
425 | .ui-icon-triangle-1-w { background-position: -96px -16px; }
426 | .ui-icon-triangle-1-nw { background-position: -112px -16px; }
427 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
428 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
429 | .ui-icon-arrow-1-n { background-position: 0 -32px; }
430 | .ui-icon-arrow-1-ne { background-position: -16px -32px; }
431 | .ui-icon-arrow-1-e { background-position: -32px -32px; }
432 | .ui-icon-arrow-1-se { background-position: -48px -32px; }
433 | .ui-icon-arrow-1-s { background-position: -64px -32px; }
434 | .ui-icon-arrow-1-sw { background-position: -80px -32px; }
435 | .ui-icon-arrow-1-w { background-position: -96px -32px; }
436 | .ui-icon-arrow-1-nw { background-position: -112px -32px; }
437 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
438 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
439 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
440 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
441 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
442 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
443 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
444 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
445 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
446 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
447 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
448 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
449 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
450 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
451 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
452 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
453 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
454 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
455 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
456 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
457 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
458 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
459 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
460 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
461 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
462 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
463 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
464 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
465 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
466 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
467 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
468 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
469 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
470 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
471 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
472 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
473 | .ui-icon-arrow-4 { background-position: 0 -80px; }
474 | .ui-icon-arrow-4-diag { background-position: -16px -80px; }
475 | .ui-icon-extlink { background-position: -32px -80px; }
476 | .ui-icon-newwin { background-position: -48px -80px; }
477 | .ui-icon-refresh { background-position: -64px -80px; }
478 | .ui-icon-shuffle { background-position: -80px -80px; }
479 | .ui-icon-transfer-e-w { background-position: -96px -80px; }
480 | .ui-icon-transferthick-e-w { background-position: -112px -80px; }
481 | .ui-icon-folder-collapsed { background-position: 0 -96px; }
482 | .ui-icon-folder-open { background-position: -16px -96px; }
483 | .ui-icon-document { background-position: -32px -96px; }
484 | .ui-icon-document-b { background-position: -48px -96px; }
485 | .ui-icon-note { background-position: -64px -96px; }
486 | .ui-icon-mail-closed { background-position: -80px -96px; }
487 | .ui-icon-mail-open { background-position: -96px -96px; }
488 | .ui-icon-suitcase { background-position: -112px -96px; }
489 | .ui-icon-comment { background-position: -128px -96px; }
490 | .ui-icon-person { background-position: -144px -96px; }
491 | .ui-icon-print { background-position: -160px -96px; }
492 | .ui-icon-trash { background-position: -176px -96px; }
493 | .ui-icon-locked { background-position: -192px -96px; }
494 | .ui-icon-unlocked { background-position: -208px -96px; }
495 | .ui-icon-bookmark { background-position: -224px -96px; }
496 | .ui-icon-tag { background-position: -240px -96px; }
497 | .ui-icon-home { background-position: 0 -112px; }
498 | .ui-icon-flag { background-position: -16px -112px; }
499 | .ui-icon-calendar { background-position: -32px -112px; }
500 | .ui-icon-cart { background-position: -48px -112px; }
501 | .ui-icon-pencil { background-position: -64px -112px; }
502 | .ui-icon-clock { background-position: -80px -112px; }
503 | .ui-icon-disk { background-position: -96px -112px; }
504 | .ui-icon-calculator { background-position: -112px -112px; }
505 | .ui-icon-zoomin { background-position: -128px -112px; }
506 | .ui-icon-zoomout { background-position: -144px -112px; }
507 | .ui-icon-search { background-position: -160px -112px; }
508 | .ui-icon-wrench { background-position: -176px -112px; }
509 | .ui-icon-gear { background-position: -192px -112px; }
510 | .ui-icon-heart { background-position: -208px -112px; }
511 | .ui-icon-star { background-position: -224px -112px; }
512 | .ui-icon-link { background-position: -240px -112px; }
513 | .ui-icon-cancel { background-position: 0 -128px; }
514 | .ui-icon-plus { background-position: -16px -128px; }
515 | .ui-icon-plusthick { background-position: -32px -128px; }
516 | .ui-icon-minus { background-position: -48px -128px; }
517 | .ui-icon-minusthick { background-position: -64px -128px; }
518 | .ui-icon-close { background-position: -80px -128px; }
519 | .ui-icon-closethick { background-position: -96px -128px; }
520 | .ui-icon-key { background-position: -112px -128px; }
521 | .ui-icon-lightbulb { background-position: -128px -128px; }
522 | .ui-icon-scissors { background-position: -144px -128px; }
523 | .ui-icon-clipboard { background-position: -160px -128px; }
524 | .ui-icon-copy { background-position: -176px -128px; }
525 | .ui-icon-contact { background-position: -192px -128px; }
526 | .ui-icon-image { background-position: -208px -128px; }
527 | .ui-icon-video { background-position: -224px -128px; }
528 | .ui-icon-script { background-position: -240px -128px; }
529 | .ui-icon-alert { background-position: 0 -144px; }
530 | .ui-icon-info { background-position: -16px -144px; }
531 | .ui-icon-notice { background-position: -32px -144px; }
532 | .ui-icon-help { background-position: -48px -144px; }
533 | .ui-icon-check { background-position: -64px -144px; }
534 | .ui-icon-bullet { background-position: -80px -144px; }
535 | .ui-icon-radio-off { background-position: -96px -144px; }
536 | .ui-icon-radio-on { background-position: -112px -144px; }
537 | .ui-icon-pin-w { background-position: -128px -144px; }
538 | .ui-icon-pin-s { background-position: -144px -144px; }
539 | .ui-icon-play { background-position: 0 -160px; }
540 | .ui-icon-pause { background-position: -16px -160px; }
541 | .ui-icon-seek-next { background-position: -32px -160px; }
542 | .ui-icon-seek-prev { background-position: -48px -160px; }
543 | .ui-icon-seek-end { background-position: -64px -160px; }
544 | .ui-icon-seek-start { background-position: -80px -160px; }
545 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
546 | .ui-icon-seek-first { background-position: -80px -160px; }
547 | .ui-icon-stop { background-position: -96px -160px; }
548 | .ui-icon-eject { background-position: -112px -160px; }
549 | .ui-icon-volume-off { background-position: -128px -160px; }
550 | .ui-icon-volume-on { background-position: -144px -160px; }
551 | .ui-icon-power { background-position: 0 -176px; }
552 | .ui-icon-signal-diag { background-position: -16px -176px; }
553 | .ui-icon-signal { background-position: -32px -176px; }
554 | .ui-icon-battery-0 { background-position: -48px -176px; }
555 | .ui-icon-battery-1 { background-position: -64px -176px; }
556 | .ui-icon-battery-2 { background-position: -80px -176px; }
557 | .ui-icon-battery-3 { background-position: -96px -176px; }
558 | .ui-icon-circle-plus { background-position: 0 -192px; }
559 | .ui-icon-circle-minus { background-position: -16px -192px; }
560 | .ui-icon-circle-close { background-position: -32px -192px; }
561 | .ui-icon-circle-triangle-e { background-position: -48px -192px; }
562 | .ui-icon-circle-triangle-s { background-position: -64px -192px; }
563 | .ui-icon-circle-triangle-w { background-position: -80px -192px; }
564 | .ui-icon-circle-triangle-n { background-position: -96px -192px; }
565 | .ui-icon-circle-arrow-e { background-position: -112px -192px; }
566 | .ui-icon-circle-arrow-s { background-position: -128px -192px; }
567 | .ui-icon-circle-arrow-w { background-position: -144px -192px; }
568 | .ui-icon-circle-arrow-n { background-position: -160px -192px; }
569 | .ui-icon-circle-zoomin { background-position: -176px -192px; }
570 | .ui-icon-circle-zoomout { background-position: -192px -192px; }
571 | .ui-icon-circle-check { background-position: -208px -192px; }
572 | .ui-icon-circlesmall-plus { background-position: 0 -208px; }
573 | .ui-icon-circlesmall-minus { background-position: -16px -208px; }
574 | .ui-icon-circlesmall-close { background-position: -32px -208px; }
575 | .ui-icon-squaresmall-plus { background-position: -48px -208px; }
576 | .ui-icon-squaresmall-minus { background-position: -64px -208px; }
577 | .ui-icon-squaresmall-close { background-position: -80px -208px; }
578 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
579 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
580 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
581 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
582 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
583 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
584 |
585 |
586 | /* Misc visuals
587 | ----------------------------------*/
588 |
589 | /* Corner radius */
590 | .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
591 | .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
592 | .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
593 | .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
594 | .ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
595 | .ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
596 | .ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
597 | .ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
598 | .ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; border-radius: 4px/*{cornerRadius}*/; }
599 |
600 | /* Overlays */
601 | .ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(img/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
602 | .ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(img/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }
--------------------------------------------------------------------------------
/tpl/styles/config.scss:
--------------------------------------------------------------------------------
1 | // theme config
2 | // Navajo
3 | $mainColor: NavajoWhite;
4 | $borderColor: darken($mainColor, 20%);
5 | $shadowColor: #ccc;
6 | $documentBgColor: lighten($mainColor, 10%);
7 | $textColor: black;
8 | // Silver
9 | $mainColor: #eee;
10 | $borderColor: darken($mainColor, 20%);
11 | $documentBgColor: lighten($mainColor, 2%);
12 | // Dark gray
13 | // $mainColor: #444;
14 | // $borderColor: darken($mainColor, 20%);
15 | // $textColor: white;
16 | // $documentBgColor: #333;
17 | // $shadowColor: #111;
18 | // $ruleChannel: #8e8eda;
19 | // $rulePort: #8e8eda;
20 | // $ruleComment: #8e8eda;
21 | // $ruleDrop: #d44f4f;
22 |
23 | $fontSize: 12px;
24 |
25 | // table
26 | $tableTextColor: $textColor;
27 | $tableBgColor: $mainColor;
28 | $tableHeaderColor: white;
29 | $tableHeaderBgColor: darken($mainColor, 40%);
30 | $tableRowBgColor: darken($mainColor, 5%);
31 |
32 | // rule highlight
33 | $ruleDrop: red;
34 | $ruleAccept: green;
35 | $ruleNetworkAddress: gray;
36 | $rulePort: blue;
37 | $ruleComment: blue;
38 | $ruleChannel: blue;
39 |
40 | // info panels
41 | $errorTextColor: white;
42 | $errorBgColor: #f88;
43 | $infoTextColor: black;
44 | $infoBgColor: lightgreen;
45 |
46 | // menu
47 | $menuTextColor: $textColor;
48 | $menuBorderColor: $borderColor;
49 | $menuLightBgColor: $mainColor;
50 | $menuDarkBgColor: darken($menuLightBgColor, 7%);
51 | $menuSelectedBgColor: darken($menuLightBgColor, 30%);
52 | $subMenuBgColor: $mainColor;
53 | $subMenuBorderColor: $borderColor;
54 | $subMenuItemColor: darken($subMenuBgColor, 10%);
55 |
56 | // tool buttons
57 | $btnTextColor: $textColor;
58 | $btnBorderColor: $borderColor;
59 | $btnLightBgColor: $mainColor;
60 | $btnDarkBgColor: darken($menuLightBgColor, 7%);
61 |
62 | // ui dialogs
63 | $dlgTextColor: $textColor;
64 | $dlgBgColor: $mainColor;
65 | $dlgCaptionBgColor: darken($mainColor, 40%);
66 |
67 | $listItemActiveBgColor: darken($mainColor, 5%);
68 | $listItemSelectedBgColor: darken($mainColor, 15%);
69 |
--------------------------------------------------------------------------------
/tpl/styles/style.scss:
--------------------------------------------------------------------------------
1 | @import "config.scss";
2 |
3 | html, body {
4 | padding: 0;
5 | margin: 0;
6 | font-size: $fontSize;
7 | background-color: $documentBgColor;
8 | }
9 |
10 | .content {
11 | width: 1000px;
12 | margin: auto;
13 | }
14 |
15 | input {
16 | margin: 0;
17 | border: 1px solid $borderColor;
18 | color: $textColor;
19 | background-color: $documentBgColor;
20 | }
21 |
22 | .chainpath {
23 | padding: 4px;
24 | color: $textColor;
25 | }
26 |
27 | // table style
28 | .main {
29 | border: 1px solid $borderColor;
30 | background-color: $tableBgColor;
31 | color: $tableTextColor;
32 | width: 100%;
33 |
34 | .ruleeditor {
35 | font-family: monospace;
36 | }
37 | input {
38 | width: 100%;
39 | }
40 |
41 | // columns title
42 | th { color: $tableHeaderColor; background-color: $tableHeaderBgColor; }
43 | .id {
44 | width: 30px;
45 | text-align: center;
46 | }
47 | .mon {
48 | width: 46px;
49 | text-align: center;
50 | }
51 | .rule {
52 | text-align: center;
53 | }
54 | .cmd {
55 | width: 35px;
56 | text-align: center;
57 | }
58 |
59 | // rows body
60 | .row {
61 | background-color: $tableRowBgColor;
62 | height: 21px;
63 | padding: 0 5px;
64 |
65 | .edit {
66 | display: none;
67 | cursor: pointer;
68 | position: absolute;
69 | margin-top: 0px;
70 | }
71 | .edittext:hover .edit {
72 | display: inherit;
73 | }
74 | }
75 | .rowright {
76 | background-color: $tableRowBgColor;
77 | text-align: right;
78 | }
79 | .rowcenter {
80 | background-color: $tableRowBgColor;
81 | text-align: center;
82 | }
83 |
84 | .newrulerow {
85 | td:nth-child(1) { text-align: right; }
86 | td:nth-child(3) { text-align: center; }
87 | }
88 | }
89 |
90 | // Highlight styles
91 | .ipt-DROP {
92 | color: $ruleDrop;
93 | }
94 |
95 | .ipt-ACCEPT {
96 | color: $ruleAccept;
97 | }
98 |
99 | .ipt-net {
100 | color: $ruleNetworkAddress;
101 | }
102 |
103 | .ipt-port {
104 | color: $rulePort;
105 | }
106 |
107 | .ipt-channel {
108 | color: $ruleChannel;
109 | }
110 |
111 | .ipt-comment {
112 | color: $ruleComment;
113 | font-style: italic;
114 | }
115 |
116 | // panels
117 | .error {
118 | color: $errorTextColor;
119 | padding: 15px;
120 | text-align: center;
121 | display: none;
122 | border: 1px solid darken($errorBgColor, 15%);
123 | background-color: $errorBgColor;
124 | cursor: pointer;
125 | position: static;
126 | }
127 |
128 | .info {
129 | color: $infoTextColor;
130 | padding: 15px;
131 | text-align: center;
132 | display: none;
133 | border: 1px solid darken($infoBgColor, 15%);
134 | background-color: $infoBgColor;
135 | cursor: pointer;
136 | position: static;
137 | }
138 |
139 | @mixin gradient($from, $to) {
140 | background: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
141 | background: -moz-linear-gradient(top, $from, $to);
142 | background-image: -o-linear-gradient(top, $from, $to);
143 | background: -ms-linear-gradient(top, $from, $to);
144 | }
145 |
146 | /* Main menu */
147 | .mainmenu {
148 | border: 1px solid $menuBorderColor; color: $menuTextColor;
149 | margin: 5px auto 0;
150 | border-radius: 5px;
151 | padding: 3px;
152 | text-align: center;
153 | @include gradient($menuLightBgColor, $menuDarkBgColor);
154 | }
155 |
156 | ul {
157 | &.tabs {
158 | display: table; padding: 0 0px; list-style: none; position: relative;
159 | li {
160 | margin: 0; padding: 0; list-style: none; display: table-cell; float: left; position: relative;
161 | &:hover {
162 | @include gradient(lighten($menuLightBgColor, 7%), lighten($menuDarkBgColor, 7%));
163 | &:first-child { border-top-left-radius: 5px; border-bottom-left-radius: 5px; }
164 | &:last-child { border-top-right-radius: 5px; border-bottom-right-radius: 5px; }
165 | }
166 | }
167 | a { position: relative; display: block; cursor: pointer; }
168 | .item {
169 | padding: 4px 15px;
170 | text-decoration: none;
171 | }
172 | .itemselect {
173 | padding: 4px 15px;
174 | text-decoration: none;
175 | background-color: $menuSelectedBgColor;
176 | }
177 | }
178 |
179 | &.dropdown {
180 | margin: 0 0 0 -36px;
181 | padding: 0px;
182 | display: block;
183 | position: absolute;
184 | z-index: 999;
185 | top: 100%; left: 0;
186 | display: none;
187 | border: 1px solid $subMenuBorderColor;
188 | background-color: $subMenuBgColor;
189 | box-shadow: 0 0 4px $shadowColor;
190 |
191 | ul.dropdown { top: 0; left: 95%; }
192 | li {
193 | margin: 0; padding: 1px; float: none; position: relative; list-style: none; display: block;
194 | &:hover { background: none; }
195 | a {
196 | display: block; padding: 5px 15px; text-decoration: none; text-align: center; width: 200px;
197 | background-color: $subMenuItemColor;
198 | &:hover { background-color: lighten($subMenuItemColor, 7%); }
199 | }
200 | }
201 | .first-row { float:left; }
202 | .second-row { float:right; }
203 | .large { width: 284px; left:-60px; }
204 | }
205 | }
206 |
207 | /* Tool buttons */
208 | .tools {
209 | padding: 10px;
210 | height: 24px;
211 | text-align: center;
212 |
213 | .button {
214 | color: $btnTextColor;
215 | padding: 5px 11px;
216 | text-decoration: none;
217 | float:right;
218 | cursor: pointer;
219 | height: 15px;
220 | margin-left: 5px;
221 | border-radius: 5px;
222 | @include gradient($btnLightBgColor, $btnDarkBgColor);
223 | border: 1px solid $btnBorderColor;
224 | box-shadow: 0 0 5px $shadowColor;
225 |
226 | &:hover {
227 | @include gradient(lighten($btnLightBgColor, 7%), lighten($btnDarkBgColor, 7%));
228 | }
229 |
230 | &[disabled=disabled] {
231 | background-color: #ccc;
232 | color:#999;
233 | @include gradient(darken($btnLightBgColor, 7%), darken($btnDarkBgColor, 7%));
234 | cursor: default;
235 | }
236 | .icon { float: right; margin: 0 4px; }
237 | }
238 | }
239 |
240 | /* Dialogs */
241 | .settings {
242 | display: none;
243 |
244 | .splitter {
245 | background-color: darken($mainColor, 5%);
246 | padding: 3px;
247 | font-weight: bold;
248 | }
249 | }
250 |
251 | .addchain {
252 | display: none;
253 | }
254 |
255 | .dialog {
256 | display: none;
257 | .content {
258 | display: flex;
259 | flex-direction: column;
260 | height: 100%;
261 | width: 100%;
262 |
263 | .params {
264 | padding-bottom: 10px;
265 | input {
266 | margin: 3px;
267 | width: 115px;
268 | }
269 | }
270 | .logpanel {
271 | overflow: auto;
272 | white-space: nowrap;
273 | flex-grow: 1;
274 | }
275 | }
276 | }
277 |
278 | #user-select-category {
279 | height: 200px; width: 140px;
280 | border: 1px solid $borderColor;
281 | vertical-align: top; float: left;
282 |
283 | .item {
284 | padding: 3px;
285 | &:hover { background-color: $listItemActiveBgColor; cursor: pointer; }
286 | }
287 | .itemselected { padding: 3px; background-color: $listItemSelectedBgColor; }
288 | .item-icon { float: left; margin-right: 5px; }
289 | }
290 |
291 | #settings-page1, #settings-page2, #settings-page3 {
292 | height: 200px; padding: 0px; display: none;
293 | border: 1px solid $borderColor;
294 | vertical-align: top; margin-left: 145px; overflow: auto;
295 | }
296 |
297 | .authform {
298 | border: 1px solid gray;
299 | background-color: #ccc;
300 | margin: auto;
301 | margin-top: 100px;
302 | padding: 15px;
303 |
304 | td {
305 | text-align: right;
306 | }
307 | }
308 |
309 | .ui-dialog {
310 | background-color: $dlgBgColor !important;
311 | box-shadow: 5px 5px 10px $shadowColor;
312 | .ui-widget-header { background: $dlgCaptionBgColor !important; }
313 | .ui-widget-content { background: transparent !important; color: $dlgTextColor !important; }
314 | .ui-dialog-buttonpane { padding: 0; }
315 | .ui-state-hover {
316 | background: darken($mainColor, 30%);
317 | box-shadow: inherit;
318 | border-color: $borderColor;
319 | }
320 | .ui-button {
321 | box-shadow: 0 0 5px $shadowColor;
322 | color: $btnTextColor;
323 | margin-left: 5px;
324 | border-radius: 5px;
325 | border: 1px solid $btnBorderColor;
326 | @include gradient($btnLightBgColor, $btnDarkBgColor);
327 | &:hover { @include gradient(lighten($btnLightBgColor, 7%), lighten($btnDarkBgColor, 7%)); }
328 | }
329 | .main { border: 0; margin-top: 0; }
330 | }
331 |
332 | @media(max-width:1000px) {
333 | .content { width: inherit; }
334 | .button { margin-bottom: 5px; }
335 | .ui-dialog { left: 0; max-width: 95%; }
336 | #logs div { white-space: nowrap; }
337 | }
--------------------------------------------------------------------------------
/tpl/template.js:
--------------------------------------------------------------------------------
1 | var tpl = {
2 | // settings
3 | settingsLan: function (interface, name) {
4 | return '\n\
5 | \n\
6 | \n\
7 | \n\
8 | ';
9 | },
10 |
11 | settingsPort: function (port, name) {
12 | return '\n\
13 | \n\
14 | \n\
15 | \n\
16 | ';
17 | },
18 |
19 | // custom chains menu
20 | customChain: function (name, table) {
21 | return '' + name + " (" + table + ') ';
22 | },
23 |
24 | customChainAddNew: 'Add new ... ',
25 |
26 | // rules
27 | ruleRow: function (index, text) {
28 | return "" +
29 | '' + index + " " +
30 | ' ' +
31 | ' ' +
32 | '' + text + ' ' +
33 | (index ? ' ' + " " : ' ') +
34 | " ";
35 | },
36 | };
37 |
38 |
--------------------------------------------------------------------------------
/tpl/theme/DarkGray.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | padding: 0;
3 | margin: 0;
4 | font-size: 12px;
5 | background-color: #333;
6 | }
7 |
8 | .content {
9 | width: 1000px;
10 | margin: auto;
11 | }
12 |
13 | input {
14 | margin: 0;
15 | border: 1px solid #111111;
16 | color: white;
17 | background-color: #333;
18 | }
19 |
20 | .chainpath {
21 | padding: 4px;
22 | color: white;
23 | }
24 |
25 | .main {
26 | border: 1px solid #111111;
27 | background-color: #444;
28 | color: white;
29 | width: 100%;
30 | }
31 | .main .ruleeditor {
32 | font-family: monospace;
33 | }
34 | .main input {
35 | width: 100%;
36 | }
37 | .main th {
38 | color: white;
39 | background-color: black;
40 | }
41 | .main .id {
42 | width: 30px;
43 | text-align: center;
44 | }
45 | .main .mon {
46 | width: 46px;
47 | text-align: center;
48 | }
49 | .main .rule {
50 | text-align: center;
51 | }
52 | .main .cmd {
53 | width: 35px;
54 | text-align: center;
55 | }
56 | .main .row {
57 | background-color: #373737;
58 | height: 21px;
59 | padding: 0 5px;
60 | }
61 | .main .row .edit {
62 | display: none;
63 | cursor: pointer;
64 | position: absolute;
65 | margin-top: 0px;
66 | }
67 | .main .row .edittext:hover .edit {
68 | display: inherit;
69 | }
70 | .main .rowright {
71 | background-color: #373737;
72 | text-align: right;
73 | }
74 | .main .rowcenter {
75 | background-color: #373737;
76 | text-align: center;
77 | }
78 | .main .newrulerow td:nth-child(1) {
79 | text-align: right;
80 | }
81 | .main .newrulerow td:nth-child(3) {
82 | text-align: center;
83 | }
84 |
85 | .ipt-DROP {
86 | color: #d44f4f;
87 | }
88 |
89 | .ipt-ACCEPT {
90 | color: green;
91 | }
92 |
93 | .ipt-net {
94 | color: gray;
95 | }
96 |
97 | .ipt-port {
98 | color: #8e8eda;
99 | }
100 |
101 | .ipt-channel {
102 | color: #8e8eda;
103 | }
104 |
105 | .ipt-comment {
106 | color: #8e8eda;
107 | font-style: italic;
108 | }
109 |
110 | .error {
111 | color: white;
112 | padding: 15px;
113 | text-align: center;
114 | display: none;
115 | border: 1px solid #ff3c3c;
116 | background-color: #f88;
117 | cursor: pointer;
118 | position: static;
119 | }
120 |
121 | .info {
122 | color: black;
123 | padding: 15px;
124 | text-align: center;
125 | display: none;
126 | border: 1px solid #4ee44e;
127 | background-color: lightgreen;
128 | cursor: pointer;
129 | position: static;
130 | }
131 |
132 | /* Main menu */
133 | .mainmenu {
134 | border: 1px solid #111111;
135 | color: white;
136 | margin: 5px auto 0;
137 | border-radius: 5px;
138 | padding: 3px;
139 | text-align: center;
140 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#323232));
141 | background: -moz-linear-gradient(top, #444, #323232);
142 | background-image: -o-linear-gradient(top, #444, #323232);
143 | background: -ms-linear-gradient(top, #444, #323232);
144 | }
145 |
146 | ul.tabs {
147 | display: table;
148 | padding: 0 0px;
149 | list-style: none;
150 | position: relative;
151 | }
152 | ul.tabs li {
153 | margin: 0;
154 | padding: 0;
155 | list-style: none;
156 | display: table-cell;
157 | float: left;
158 | position: relative;
159 | }
160 | ul.tabs li:hover {
161 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#565656), to(#444444));
162 | background: -moz-linear-gradient(top, #565656, #444444);
163 | background-image: -o-linear-gradient(top, #565656, #444444);
164 | background: -ms-linear-gradient(top, #565656, #444444);
165 | }
166 | ul.tabs li:hover:first-child {
167 | border-top-left-radius: 5px;
168 | border-bottom-left-radius: 5px;
169 | }
170 | ul.tabs li:hover:last-child {
171 | border-top-right-radius: 5px;
172 | border-bottom-right-radius: 5px;
173 | }
174 | ul.tabs a {
175 | position: relative;
176 | display: block;
177 | cursor: pointer;
178 | }
179 | ul.tabs .item {
180 | padding: 4px 15px;
181 | text-decoration: none;
182 | }
183 | ul.tabs .itemselect {
184 | padding: 4px 15px;
185 | text-decoration: none;
186 | background-color: black;
187 | }
188 | ul.dropdown {
189 | margin: 0 0 0 -36px;
190 | padding: 0px;
191 | display: block;
192 | position: absolute;
193 | z-index: 999;
194 | top: 100%;
195 | left: 0;
196 | display: none;
197 | border: 1px solid #111111;
198 | background-color: #444;
199 | box-shadow: 0 0 4px #111;
200 | }
201 | ul.dropdown ul.dropdown {
202 | top: 0;
203 | left: 95%;
204 | }
205 | ul.dropdown li {
206 | margin: 0;
207 | padding: 1px;
208 | float: none;
209 | position: relative;
210 | list-style: none;
211 | display: block;
212 | }
213 | ul.dropdown li:hover {
214 | background: none;
215 | }
216 | ul.dropdown li a {
217 | display: block;
218 | padding: 5px 15px;
219 | text-decoration: none;
220 | text-align: center;
221 | width: 200px;
222 | background-color: #2b2b2b;
223 | }
224 | ul.dropdown li a:hover {
225 | background-color: #3c3c3c;
226 | }
227 | ul.dropdown .first-row {
228 | float: left;
229 | }
230 | ul.dropdown .second-row {
231 | float: right;
232 | }
233 | ul.dropdown .large {
234 | width: 284px;
235 | left: -60px;
236 | }
237 |
238 | /* Tool buttons */
239 | .tools {
240 | padding: 10px;
241 | height: 24px;
242 | text-align: center;
243 | }
244 | .tools .button {
245 | color: white;
246 | padding: 5px 11px;
247 | text-decoration: none;
248 | float: right;
249 | cursor: pointer;
250 | height: 15px;
251 | margin-left: 5px;
252 | border-radius: 5px;
253 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#323232));
254 | background: -moz-linear-gradient(top, #444, #323232);
255 | background-image: -o-linear-gradient(top, #444, #323232);
256 | background: -ms-linear-gradient(top, #444, #323232);
257 | border: 1px solid #111111;
258 | box-shadow: 0 0 5px #111;
259 | }
260 | .tools .button:hover {
261 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#565656), to(#444444));
262 | background: -moz-linear-gradient(top, #565656, #444444);
263 | background-image: -o-linear-gradient(top, #565656, #444444);
264 | background: -ms-linear-gradient(top, #565656, #444444);
265 | }
266 | .tools .button[disabled=disabled] {
267 | background-color: #ccc;
268 | color: #999;
269 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#323232), to(#202020));
270 | background: -moz-linear-gradient(top, #323232, #202020);
271 | background-image: -o-linear-gradient(top, #323232, #202020);
272 | background: -ms-linear-gradient(top, #323232, #202020);
273 | cursor: default;
274 | }
275 | .tools .button .icon {
276 | float: right;
277 | margin: 0 4px;
278 | }
279 |
280 | /* Dialogs */
281 | .settings {
282 | display: none;
283 | }
284 | .settings .splitter {
285 | background-color: #373737;
286 | padding: 3px;
287 | font-weight: bold;
288 | }
289 |
290 | .addchain {
291 | display: none;
292 | }
293 |
294 | .dialog {
295 | display: none;
296 | }
297 | .dialog .content {
298 | display: flex;
299 | flex-direction: column;
300 | height: 100%;
301 | width: 100%;
302 | }
303 | .dialog .content .params {
304 | padding-bottom: 10px;
305 | }
306 | .dialog .content .params input {
307 | margin: 3px;
308 | width: 115px;
309 | }
310 | .dialog .content .logpanel {
311 | overflow: auto;
312 | white-space: nowrap;
313 | flex-grow: 1;
314 | }
315 |
316 | #user-select-category {
317 | height: 200px;
318 | width: 140px;
319 | border: 1px solid #111111;
320 | vertical-align: top;
321 | float: left;
322 | }
323 | #user-select-category .item {
324 | padding: 3px;
325 | }
326 | #user-select-category .item:hover {
327 | background-color: #373737;
328 | cursor: pointer;
329 | }
330 | #user-select-category .itemselected {
331 | padding: 3px;
332 | background-color: #1e1e1e;
333 | }
334 | #user-select-category .item-icon {
335 | float: left;
336 | margin-right: 5px;
337 | }
338 |
339 | #settings-page1, #settings-page2, #settings-page3 {
340 | height: 200px;
341 | padding: 0px;
342 | display: none;
343 | border: 1px solid #111111;
344 | vertical-align: top;
345 | margin-left: 145px;
346 | overflow: auto;
347 | }
348 |
349 | .authform {
350 | border: 1px solid gray;
351 | background-color: #ccc;
352 | margin: auto;
353 | margin-top: 100px;
354 | padding: 15px;
355 | }
356 | .authform td {
357 | text-align: right;
358 | }
359 |
360 | .ui-dialog {
361 | background-color: #444 !important;
362 | box-shadow: 5px 5px 10px #111;
363 | }
364 | .ui-dialog .ui-widget-header {
365 | background: black !important;
366 | }
367 | .ui-dialog .ui-widget-content {
368 | background: transparent !important;
369 | color: white !important;
370 | }
371 | .ui-dialog .ui-dialog-buttonpane {
372 | padding: 0;
373 | }
374 | .ui-dialog .ui-state-hover {
375 | background: black;
376 | box-shadow: inherit;
377 | border-color: #111111;
378 | }
379 | .ui-dialog .ui-button {
380 | box-shadow: 0 0 5px #111;
381 | color: white;
382 | margin-left: 5px;
383 | border-radius: 5px;
384 | border: 1px solid #111111;
385 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#323232));
386 | background: -moz-linear-gradient(top, #444, #323232);
387 | background-image: -o-linear-gradient(top, #444, #323232);
388 | background: -ms-linear-gradient(top, #444, #323232);
389 | }
390 | .ui-dialog .ui-button:hover {
391 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#565656), to(#444444));
392 | background: -moz-linear-gradient(top, #565656, #444444);
393 | background-image: -o-linear-gradient(top, #565656, #444444);
394 | background: -ms-linear-gradient(top, #565656, #444444);
395 | }
396 | .ui-dialog .main {
397 | border: 0;
398 | margin-top: 0;
399 | }
400 |
401 | @media (max-width: 1000px) {
402 | .content {
403 | width: inherit;
404 | }
405 |
406 | .button {
407 | margin-bottom: 5px;
408 | }
409 |
410 | .ui-dialog {
411 | left: 0;
412 | max-width: 95%;
413 | }
414 |
415 | #logs div {
416 | white-space: nowrap;
417 | }
418 | }
419 |
--------------------------------------------------------------------------------
/tpl/theme/Navajo.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | padding: 0;
3 | margin: 0;
4 | font-size: 12px;
5 | background-color: #fff3e0;
6 | }
7 |
8 | .content {
9 | width: 1000px;
10 | margin: auto;
11 | }
12 |
13 | input {
14 | margin: 0;
15 | border: 1px solid #ffb547;
16 | color: black;
17 | background-color: #fff3e0;
18 | }
19 |
20 | .chainpath {
21 | padding: 4px;
22 | color: black;
23 | }
24 |
25 | .main {
26 | border: 1px solid #ffb547;
27 | background-color: NavajoWhite;
28 | color: black;
29 | width: 100%;
30 | }
31 | .main .ruleeditor {
32 | font-family: monospace;
33 | }
34 | .main input {
35 | width: 100%;
36 | }
37 | .main th {
38 | color: white;
39 | background-color: #e08600;
40 | }
41 | .main .id {
42 | width: 30px;
43 | text-align: center;
44 | }
45 | .main .mon {
46 | width: 46px;
47 | text-align: center;
48 | }
49 | .main .rule {
50 | text-align: center;
51 | }
52 | .main .cmd {
53 | width: 35px;
54 | text-align: center;
55 | }
56 | .main .row {
57 | background-color: #ffd494;
58 | height: 21px;
59 | padding: 0 5px;
60 | }
61 | .main .row .edit {
62 | display: none;
63 | cursor: pointer;
64 | position: absolute;
65 | margin-top: 0px;
66 | }
67 | .main .row .edittext:hover .edit {
68 | display: inherit;
69 | }
70 | .main .rowright {
71 | background-color: #ffd494;
72 | text-align: right;
73 | }
74 | .main .rowcenter {
75 | background-color: #ffd494;
76 | text-align: center;
77 | }
78 | .main .newrulerow td:nth-child(1) {
79 | text-align: right;
80 | }
81 | .main .newrulerow td:nth-child(3) {
82 | text-align: center;
83 | }
84 |
85 | .ipt-DROP {
86 | color: red;
87 | }
88 |
89 | .ipt-ACCEPT {
90 | color: green;
91 | }
92 |
93 | .ipt-net {
94 | color: gray;
95 | }
96 |
97 | .ipt-port {
98 | color: blue;
99 | }
100 |
101 | .ipt-channel {
102 | color: blue;
103 | }
104 |
105 | .ipt-comment {
106 | color: blue;
107 | font-style: italic;
108 | }
109 |
110 | .error {
111 | color: white;
112 | padding: 15px;
113 | text-align: center;
114 | display: none;
115 | border: 1px solid #ff3c3c;
116 | background-color: #f88;
117 | cursor: pointer;
118 | position: static;
119 | }
120 |
121 | .info {
122 | color: black;
123 | padding: 15px;
124 | text-align: center;
125 | display: none;
126 | border: 1px solid #4ee44e;
127 | background-color: lightgreen;
128 | cursor: pointer;
129 | position: static;
130 | }
131 |
132 | /* Main menu */
133 | .mainmenu {
134 | border: 1px solid #ffb547;
135 | color: black;
136 | margin: 5px auto 0;
137 | border-radius: 5px;
138 | padding: 3px;
139 | text-align: center;
140 | background: -webkit-gradient(linear, 0 0, 0 100%, from(NavajoWhite), to(#ffd089));
141 | background: -moz-linear-gradient(top, NavajoWhite, #ffd089);
142 | background-image: -o-linear-gradient(top, NavajoWhite, #ffd089);
143 | background: -ms-linear-gradient(top, NavajoWhite, #ffd089);
144 | }
145 |
146 | ul.tabs {
147 | display: table;
148 | padding: 0 0px;
149 | list-style: none;
150 | position: relative;
151 | }
152 | ul.tabs li {
153 | margin: 0;
154 | padding: 0;
155 | list-style: none;
156 | display: table-cell;
157 | float: left;
158 | position: relative;
159 | }
160 | ul.tabs li:hover {
161 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#ffecd1), to(navajowhite));
162 | background: -moz-linear-gradient(top, #ffecd1, navajowhite);
163 | background-image: -o-linear-gradient(top, #ffecd1, navajowhite);
164 | background: -ms-linear-gradient(top, #ffecd1, navajowhite);
165 | }
166 | ul.tabs li:hover:first-child {
167 | border-top-left-radius: 5px;
168 | border-bottom-left-radius: 5px;
169 | }
170 | ul.tabs li:hover:last-child {
171 | border-top-right-radius: 5px;
172 | border-bottom-right-radius: 5px;
173 | }
174 | ul.tabs a {
175 | position: relative;
176 | display: block;
177 | cursor: pointer;
178 | }
179 | ul.tabs .item {
180 | padding: 4px 15px;
181 | text-decoration: none;
182 | }
183 | ul.tabs .itemselect {
184 | padding: 4px 15px;
185 | text-decoration: none;
186 | background-color: #ffa014;
187 | }
188 | ul.dropdown {
189 | margin: 0 0 0 -36px;
190 | padding: 0px;
191 | display: block;
192 | position: absolute;
193 | z-index: 999;
194 | top: 100%;
195 | left: 0;
196 | display: none;
197 | border: 1px solid #ffb547;
198 | background-color: NavajoWhite;
199 | box-shadow: 0 0 4px #ccc;
200 | }
201 | ul.dropdown ul.dropdown {
202 | top: 0;
203 | left: 95%;
204 | }
205 | ul.dropdown li {
206 | margin: 0;
207 | padding: 1px;
208 | float: none;
209 | position: relative;
210 | list-style: none;
211 | display: block;
212 | }
213 | ul.dropdown li:hover {
214 | background: none;
215 | }
216 | ul.dropdown li a {
217 | display: block;
218 | padding: 5px 15px;
219 | text-decoration: none;
220 | text-align: center;
221 | width: 200px;
222 | background-color: #ffc97a;
223 | }
224 | ul.dropdown li a:hover {
225 | background-color: #ffd89e;
226 | }
227 | ul.dropdown .first-row {
228 | float: left;
229 | }
230 | ul.dropdown .second-row {
231 | float: right;
232 | }
233 | ul.dropdown .large {
234 | width: 284px;
235 | left: -60px;
236 | }
237 |
238 | /* Tool buttons */
239 | .tools {
240 | padding: 10px;
241 | height: 24px;
242 | text-align: center;
243 | }
244 | .tools .button {
245 | color: black;
246 | padding: 5px 11px;
247 | text-decoration: none;
248 | float: right;
249 | cursor: pointer;
250 | height: 15px;
251 | margin-left: 5px;
252 | border-radius: 5px;
253 | background: -webkit-gradient(linear, 0 0, 0 100%, from(NavajoWhite), to(#ffd089));
254 | background: -moz-linear-gradient(top, NavajoWhite, #ffd089);
255 | background-image: -o-linear-gradient(top, NavajoWhite, #ffd089);
256 | background: -ms-linear-gradient(top, NavajoWhite, #ffd089);
257 | border: 1px solid #ffb547;
258 | box-shadow: 0 0 5px #ccc;
259 | }
260 | .tools .button:hover {
261 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#ffecd1), to(navajowhite));
262 | background: -moz-linear-gradient(top, #ffecd1, navajowhite);
263 | background-image: -o-linear-gradient(top, #ffecd1, navajowhite);
264 | background: -ms-linear-gradient(top, #ffecd1, navajowhite);
265 | }
266 | .tools .button[disabled=disabled] {
267 | background-color: #ccc;
268 | color: #999;
269 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#ffd089), to(#ffc166));
270 | background: -moz-linear-gradient(top, #ffd089, #ffc166);
271 | background-image: -o-linear-gradient(top, #ffd089, #ffc166);
272 | background: -ms-linear-gradient(top, #ffd089, #ffc166);
273 | cursor: default;
274 | }
275 | .tools .button .icon {
276 | float: right;
277 | margin: 0 4px;
278 | }
279 |
280 | /* Dialogs */
281 | .settings {
282 | display: none;
283 | }
284 | .settings .splitter {
285 | background-color: #ffd494;
286 | padding: 3px;
287 | font-weight: bold;
288 | }
289 |
290 | .addchain {
291 | display: none;
292 | }
293 |
294 | .dialog {
295 | display: none;
296 | }
297 | .dialog .content {
298 | display: flex;
299 | flex-direction: column;
300 | height: 100%;
301 | width: 100%;
302 | }
303 | .dialog .content .params {
304 | padding-bottom: 10px;
305 | }
306 | .dialog .content .params input {
307 | margin: 3px;
308 | width: 115px;
309 | }
310 | .dialog .content .logpanel {
311 | overflow: auto;
312 | white-space: nowrap;
313 | flex-grow: 1;
314 | }
315 |
316 | #user-select-category {
317 | height: 200px;
318 | width: 140px;
319 | border: 1px solid #ffb547;
320 | vertical-align: top;
321 | float: left;
322 | }
323 | #user-select-category .item {
324 | padding: 3px;
325 | }
326 | #user-select-category .item:hover {
327 | background-color: #ffd494;
328 | cursor: pointer;
329 | }
330 | #user-select-category .itemselected {
331 | padding: 3px;
332 | background-color: #ffbf61;
333 | }
334 | #user-select-category .item-icon {
335 | float: left;
336 | margin-right: 5px;
337 | }
338 |
339 | #settings-page1, #settings-page2, #settings-page3 {
340 | height: 200px;
341 | padding: 0px;
342 | display: none;
343 | border: 1px solid #ffb547;
344 | vertical-align: top;
345 | margin-left: 145px;
346 | overflow: auto;
347 | }
348 |
349 | .authform {
350 | border: 1px solid gray;
351 | background-color: #ccc;
352 | margin: auto;
353 | margin-top: 100px;
354 | padding: 15px;
355 | }
356 | .authform td {
357 | text-align: right;
358 | }
359 |
360 | .ui-dialog {
361 | background-color: NavajoWhite !important;
362 | box-shadow: 5px 5px 10px #ccc;
363 | }
364 | .ui-dialog .ui-widget-header {
365 | background: #e08600 !important;
366 | }
367 | .ui-dialog .ui-widget-content {
368 | background: transparent !important;
369 | color: black !important;
370 | }
371 | .ui-dialog .ui-dialog-buttonpane {
372 | padding: 0;
373 | }
374 | .ui-dialog .ui-state-hover {
375 | background: #ffa014;
376 | box-shadow: inherit;
377 | border-color: #ffb547;
378 | }
379 | .ui-dialog .ui-button {
380 | box-shadow: 0 0 5px #ccc;
381 | color: black;
382 | margin-left: 5px;
383 | border-radius: 5px;
384 | border: 1px solid #ffb547;
385 | background: -webkit-gradient(linear, 0 0, 0 100%, from(NavajoWhite), to(#ffd089));
386 | background: -moz-linear-gradient(top, NavajoWhite, #ffd089);
387 | background-image: -o-linear-gradient(top, NavajoWhite, #ffd089);
388 | background: -ms-linear-gradient(top, NavajoWhite, #ffd089);
389 | }
390 | .ui-dialog .ui-button:hover {
391 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#ffecd1), to(navajowhite));
392 | background: -moz-linear-gradient(top, #ffecd1, navajowhite);
393 | background-image: -o-linear-gradient(top, #ffecd1, navajowhite);
394 | background: -ms-linear-gradient(top, #ffecd1, navajowhite);
395 | }
396 | .ui-dialog .main {
397 | border: 0;
398 | margin-top: 0;
399 | }
400 |
401 | @media (max-width: 1000px) {
402 | .content {
403 | width: inherit;
404 | }
405 |
406 | .button {
407 | margin-bottom: 5px;
408 | }
409 |
410 | .ui-dialog {
411 | left: 0;
412 | max-width: 95%;
413 | }
414 |
415 | #logs div {
416 | white-space: nowrap;
417 | }
418 | }
419 |
--------------------------------------------------------------------------------
/tpl/theme/Silver.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | padding: 0;
3 | margin: 0;
4 | font-size: 12px;
5 | background-color: #f3f3f3;
6 | }
7 |
8 | .content {
9 | width: 1000px;
10 | margin: auto;
11 | }
12 |
13 | input {
14 | margin: 0;
15 | border: 1px solid #bbbbbb;
16 | color: black;
17 | background-color: #f3f3f3;
18 | }
19 |
20 | .chainpath {
21 | padding: 4px;
22 | color: black;
23 | }
24 |
25 | .main {
26 | border: 1px solid #bbbbbb;
27 | background-color: #eee;
28 | color: black;
29 | width: 100%;
30 | }
31 | .main .ruleeditor {
32 | font-family: monospace;
33 | }
34 | .main input {
35 | width: 100%;
36 | }
37 | .main th {
38 | color: white;
39 | background-color: #888888;
40 | }
41 | .main .id {
42 | width: 30px;
43 | text-align: center;
44 | }
45 | .main .mon {
46 | width: 46px;
47 | text-align: center;
48 | }
49 | .main .rule {
50 | text-align: center;
51 | }
52 | .main .cmd {
53 | width: 35px;
54 | text-align: center;
55 | }
56 | .main .row {
57 | background-color: #e1e1e1;
58 | height: 21px;
59 | padding: 0 5px;
60 | }
61 | .main .row .edit {
62 | display: none;
63 | cursor: pointer;
64 | position: absolute;
65 | margin-top: 0px;
66 | }
67 | .main .row .edittext:hover .edit {
68 | display: inherit;
69 | }
70 | .main .rowright {
71 | background-color: #e1e1e1;
72 | text-align: right;
73 | }
74 | .main .rowcenter {
75 | background-color: #e1e1e1;
76 | text-align: center;
77 | }
78 | .main .newrulerow td:nth-child(1) {
79 | text-align: right;
80 | }
81 | .main .newrulerow td:nth-child(3) {
82 | text-align: center;
83 | }
84 |
85 | .ipt-DROP {
86 | color: red;
87 | }
88 |
89 | .ipt-ACCEPT {
90 | color: green;
91 | }
92 |
93 | .ipt-net {
94 | color: gray;
95 | }
96 |
97 | .ipt-port {
98 | color: blue;
99 | }
100 |
101 | .ipt-channel {
102 | color: blue;
103 | }
104 |
105 | .ipt-comment {
106 | color: blue;
107 | font-style: italic;
108 | }
109 |
110 | .error {
111 | color: white;
112 | padding: 15px;
113 | text-align: center;
114 | display: none;
115 | border: 1px solid #ff3c3c;
116 | background-color: #f88;
117 | cursor: pointer;
118 | position: static;
119 | }
120 |
121 | .info {
122 | color: black;
123 | padding: 15px;
124 | text-align: center;
125 | display: none;
126 | border: 1px solid #4ee44e;
127 | background-color: lightgreen;
128 | cursor: pointer;
129 | position: static;
130 | }
131 |
132 | /* Main menu */
133 | .mainmenu {
134 | border: 1px solid #bbbbbb;
135 | color: black;
136 | margin: 5px auto 0;
137 | border-radius: 5px;
138 | padding: 3px;
139 | text-align: center;
140 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#eee), to(gainsboro));
141 | background: -moz-linear-gradient(top, #eee, gainsboro);
142 | background-image: -o-linear-gradient(top, #eee, gainsboro);
143 | background: -ms-linear-gradient(top, #eee, gainsboro);
144 | }
145 |
146 | ul.tabs {
147 | display: table;
148 | padding: 0 0px;
149 | list-style: none;
150 | position: relative;
151 | }
152 | ul.tabs li {
153 | margin: 0;
154 | padding: 0;
155 | list-style: none;
156 | display: table-cell;
157 | float: left;
158 | position: relative;
159 | }
160 | ul.tabs li:hover {
161 | background: -webkit-gradient(linear, 0 0, 0 100%, from(white), to(#eeeeee));
162 | background: -moz-linear-gradient(top, white, #eeeeee);
163 | background-image: -o-linear-gradient(top, white, #eeeeee);
164 | background: -ms-linear-gradient(top, white, #eeeeee);
165 | }
166 | ul.tabs li:hover:first-child {
167 | border-top-left-radius: 5px;
168 | border-bottom-left-radius: 5px;
169 | }
170 | ul.tabs li:hover:last-child {
171 | border-top-right-radius: 5px;
172 | border-bottom-right-radius: 5px;
173 | }
174 | ul.tabs a {
175 | position: relative;
176 | display: block;
177 | cursor: pointer;
178 | }
179 | ul.tabs .item {
180 | padding: 4px 15px;
181 | text-decoration: none;
182 | }
183 | ul.tabs .itemselect {
184 | padding: 4px 15px;
185 | text-decoration: none;
186 | background-color: #a2a2a2;
187 | }
188 | ul.dropdown {
189 | margin: 0 0 0 -36px;
190 | padding: 0px;
191 | display: block;
192 | position: absolute;
193 | z-index: 999;
194 | top: 100%;
195 | left: 0;
196 | display: none;
197 | border: 1px solid #bbbbbb;
198 | background-color: #eee;
199 | box-shadow: 0 0 4px #ccc;
200 | }
201 | ul.dropdown ul.dropdown {
202 | top: 0;
203 | left: 95%;
204 | }
205 | ul.dropdown li {
206 | margin: 0;
207 | padding: 1px;
208 | float: none;
209 | position: relative;
210 | list-style: none;
211 | display: block;
212 | }
213 | ul.dropdown li:hover {
214 | background: none;
215 | }
216 | ul.dropdown li a {
217 | display: block;
218 | padding: 5px 15px;
219 | text-decoration: none;
220 | text-align: center;
221 | width: 200px;
222 | background-color: #d5d5d5;
223 | }
224 | ul.dropdown li a:hover {
225 | background-color: #e6e6e6;
226 | }
227 | ul.dropdown .first-row {
228 | float: left;
229 | }
230 | ul.dropdown .second-row {
231 | float: right;
232 | }
233 | ul.dropdown .large {
234 | width: 284px;
235 | left: -60px;
236 | }
237 |
238 | /* Tool buttons */
239 | .tools {
240 | padding: 10px;
241 | height: 24px;
242 | text-align: center;
243 | }
244 | .tools .button {
245 | color: black;
246 | padding: 5px 11px;
247 | text-decoration: none;
248 | float: right;
249 | cursor: pointer;
250 | height: 15px;
251 | margin-left: 5px;
252 | border-radius: 5px;
253 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#eee), to(gainsboro));
254 | background: -moz-linear-gradient(top, #eee, gainsboro);
255 | background-image: -o-linear-gradient(top, #eee, gainsboro);
256 | background: -ms-linear-gradient(top, #eee, gainsboro);
257 | border: 1px solid #bbbbbb;
258 | box-shadow: 0 0 5px #ccc;
259 | }
260 | .tools .button:hover {
261 | background: -webkit-gradient(linear, 0 0, 0 100%, from(white), to(#eeeeee));
262 | background: -moz-linear-gradient(top, white, #eeeeee);
263 | background-image: -o-linear-gradient(top, white, #eeeeee);
264 | background: -ms-linear-gradient(top, white, #eeeeee);
265 | }
266 | .tools .button[disabled=disabled] {
267 | background-color: #ccc;
268 | color: #999;
269 | background: -webkit-gradient(linear, 0 0, 0 100%, from(gainsboro), to(#cacaca));
270 | background: -moz-linear-gradient(top, gainsboro, #cacaca);
271 | background-image: -o-linear-gradient(top, gainsboro, #cacaca);
272 | background: -ms-linear-gradient(top, gainsboro, #cacaca);
273 | cursor: default;
274 | }
275 | .tools .button .icon {
276 | float: right;
277 | margin: 0 4px;
278 | }
279 |
280 | /* Dialogs */
281 | .settings {
282 | display: none;
283 | }
284 | .settings .splitter {
285 | background-color: #e1e1e1;
286 | padding: 3px;
287 | font-weight: bold;
288 | }
289 |
290 | .addchain {
291 | display: none;
292 | }
293 |
294 | .dialog {
295 | display: none;
296 | }
297 | .dialog .content {
298 | display: flex;
299 | flex-direction: column;
300 | height: 100%;
301 | width: 100%;
302 | }
303 | .dialog .content .params {
304 | padding-bottom: 10px;
305 | }
306 | .dialog .content .params input {
307 | margin: 3px;
308 | width: 115px;
309 | }
310 | .dialog .content .logpanel {
311 | overflow: auto;
312 | white-space: nowrap;
313 | flex-grow: 1;
314 | }
315 |
316 | #user-select-category {
317 | height: 200px;
318 | width: 140px;
319 | border: 1px solid #bbbbbb;
320 | vertical-align: top;
321 | float: left;
322 | }
323 | #user-select-category .item {
324 | padding: 3px;
325 | }
326 | #user-select-category .item:hover {
327 | background-color: #e1e1e1;
328 | cursor: pointer;
329 | }
330 | #user-select-category .itemselected {
331 | padding: 3px;
332 | background-color: #c8c8c8;
333 | }
334 | #user-select-category .item-icon {
335 | float: left;
336 | margin-right: 5px;
337 | }
338 |
339 | #settings-page1, #settings-page2, #settings-page3 {
340 | height: 200px;
341 | padding: 0px;
342 | display: none;
343 | border: 1px solid #bbbbbb;
344 | vertical-align: top;
345 | margin-left: 145px;
346 | overflow: auto;
347 | }
348 |
349 | .authform {
350 | border: 1px solid gray;
351 | background-color: #ccc;
352 | margin: auto;
353 | margin-top: 100px;
354 | padding: 15px;
355 | }
356 | .authform td {
357 | text-align: right;
358 | }
359 |
360 | .ui-dialog {
361 | background-color: #eee !important;
362 | box-shadow: 5px 5px 10px #ccc;
363 | }
364 | .ui-dialog .ui-widget-header {
365 | background: #888888 !important;
366 | }
367 | .ui-dialog .ui-widget-content {
368 | background: transparent !important;
369 | color: black !important;
370 | }
371 | .ui-dialog .ui-dialog-buttonpane {
372 | padding: 0;
373 | }
374 | .ui-dialog .ui-state-hover {
375 | background: #a2a2a2;
376 | box-shadow: inherit;
377 | border-color: #bbbbbb;
378 | }
379 | .ui-dialog .ui-button {
380 | box-shadow: 0 0 5px #ccc;
381 | color: black;
382 | margin-left: 5px;
383 | border-radius: 5px;
384 | border: 1px solid #bbbbbb;
385 | background: -webkit-gradient(linear, 0 0, 0 100%, from(#eee), to(gainsboro));
386 | background: -moz-linear-gradient(top, #eee, gainsboro);
387 | background-image: -o-linear-gradient(top, #eee, gainsboro);
388 | background: -ms-linear-gradient(top, #eee, gainsboro);
389 | }
390 | .ui-dialog .ui-button:hover {
391 | background: -webkit-gradient(linear, 0 0, 0 100%, from(white), to(#eeeeee));
392 | background: -moz-linear-gradient(top, white, #eeeeee);
393 | background-image: -o-linear-gradient(top, white, #eeeeee);
394 | background: -ms-linear-gradient(top, white, #eeeeee);
395 | }
396 | .ui-dialog .main {
397 | border: 0;
398 | margin-top: 0;
399 | }
400 |
401 | @media (max-width: 1000px) {
402 | .content {
403 | width: inherit;
404 | }
405 |
406 | .button {
407 | margin-bottom: 5px;
408 | }
409 |
410 | .ui-dialog {
411 | left: 0;
412 | max-width: 95%;
413 | }
414 |
415 | #logs div {
416 | white-space: nowrap;
417 | }
418 | }
419 |
--------------------------------------------------------------------------------
/tpl/tools.js:
--------------------------------------------------------------------------------
1 | _settings = {};
2 |
3 | $(document).ready(function(){
4 | $.get("/settings", function(data){
5 | _settings = JSON.parse(data);
6 | $(".param").each(function(index, obj){
7 | $(obj).val(_settings[obj.id]);
8 | });
9 |
10 | if(_settings.LANS) {
11 | for(var lan in _settings.LANS) {
12 | $("#lans").append(window.tpl.settingsLan(lan, _settings.LANS[lan]));
13 | }
14 | }
15 | else {
16 | _settings.LANS = {};
17 | }
18 | if(_settings.PORTS) {
19 | for(var port in _settings.PORTS) {
20 | $("#ports").append(window.tpl.settingsPort(port, _settings.PORTS[port]));
21 | }
22 | }
23 | else {
24 | _settings.PORTS = {};
25 | }
26 |
27 | if(_settings.pass) {
28 | $("#logout").show();
29 | }
30 |
31 | $("#theme").attr("href", "theme/" + _settings.theme + ".css");
32 | for(var i in _settings.themes) {
33 | var theme = _settings.themes[i];
34 | $("#themeSelector").append("" + theme + " ");
35 | }
36 | $("#themeSelector").on("change", function(){
37 | $("#theme").attr("href", "theme/" + this.value + ".css");
38 | _settings.theme = this.value;
39 | });
40 | });
41 | });
42 |
43 | function showError(text) {
44 | $(".error").html(text).fadeIn().click(function(){
45 | $(this).fadeOut();
46 | });
47 | }
48 |
49 | function showInfo(text) {
50 | $(".info").html(text).fadeIn().click(function(){
51 | $(this).fadeOut();
52 | });
53 | }
--------------------------------------------------------------------------------