├── README.md
├── addons
└── whmcspf
│ ├── hooks.php
│ ├── static
│ ├── css
│ │ ├── jquery-confirm.css
│ │ └── jquery-confirm.less
│ └── js
│ │ └── jquery-confirm.js
│ ├── templates.admin.php
│ └── whmcspf.php
├── pfnode
├── composer.json
├── config.php
├── database.db
├── forward_service
│ └── ForwardSystem
├── service_file_template.php
├── start.php
├── start_autoload.php
├── start_http.php
├── start_report.php
└── start_service.php
└── servers
└── portforward
├── portforward.php
├── templates
└── clientarea.tpl
└── theme
├── base64.js
├── flags.css
├── flags.png
├── jquery-confirm.css
├── jquery-confirm.js
└── style.css
/README.md:
--------------------------------------------------------------------------------
1 | # WhmcsPortForward
2 | 可以对接Whmcs进行销售的端口转发系统,支持TCP/UDP及Ipv6/Ipv4端口转发
3 |
4 | 自定义字段列表:
5 |
6 | ptype|转发协议
7 |
8 | sport
9 |
10 | rsip|源服务器IP
11 |
12 | rport|源服务器端口
13 |
14 | bandwidth
15 |
16 | forwardstatus
17 |
18 | 除'ptype|转发协议'、'rsip|源服务器IP'、'rport|源服务器端口'以外请全部设置为仅管理员可见!
19 |
20 | 'ptype|转发协议'、'rsip|源服务器IP'、'rport|源服务器端口'请设置为必填、在订单上时显示、在账单上显示!
21 |
22 | 安装:
23 |
24 | 1.安装Redis
25 |
26 | 2.apt update
27 |
28 | 3.apt install php php-posix php-pdo-sqlite php-curl
29 |
30 | 4.编辑config.php
31 |
32 | 5.Debug : php start.php start Daemon: php start.php start -d
33 |
34 | 6.Whmcs后台启用流量监控插件
35 |
36 | 7.添加服务器
37 |
38 | 8.添加产品
39 |
40 | 9.开通测试
41 |
42 | 服务器可选Hash
43 |
44 | 10.0.1.1,10.0.1.2,10.0.0.3,10.0.0.4,10.0.0.5,10.0.0.6,10.0.0.7
45 |
--------------------------------------------------------------------------------
/addons/whmcspf/hooks.php:
--------------------------------------------------------------------------------
1 | where('untime',date("Y-m-d"))->get();
5 | if($todayunsusp){
6 | foreach ( $todayunsusp as $listone){
7 | localAPI('ModuleUnsuspend', array('serviceid' => $listone->serviceid), Capsule::table('tbladmins')->first()->id);
8 | Capsule::table('tblhosting')->where('id',$listone->serviceid)->update(['domainstatus' => 'Active']);
9 | whmcspf_setCustomfieldsValue('forwardstatus','Active',$listone->serviceid,null);
10 | Capsule::table('mod_whmcspf_suspservice')->where('serviceid',$listone->serviceid)->delete();
11 | }
12 | }
13 | });
14 | add_hook('AfterModuleTerminate', 1, function($vars) {
15 | Capsule::table('mod_whmcspf_suspservice')->where('serviceid',$vars['serviceid'])->delete();
16 | });
--------------------------------------------------------------------------------
/addons/whmcspf/static/css/jquery-confirm.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * jquery-confirm v3.3.0 (http://craftpip.github.io/jquery-confirm/)
3 | * Author: boniface pereira
4 | * Website: www.craftpip.com
5 | * Contact: hey@craftpip.com
6 | *
7 | * Copyright 2013-2017 jquery-confirm
8 | * Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
9 | */
10 | @-webkit-keyframes jconfirm-spin {
11 | from {
12 | -webkit-transform: rotate(0deg);
13 | transform: rotate(0deg);
14 | }
15 | to {
16 | -webkit-transform: rotate(360deg);
17 | transform: rotate(360deg);
18 | }
19 | }
20 | @keyframes jconfirm-spin {
21 | from {
22 | -webkit-transform: rotate(0deg);
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | -webkit-transform: rotate(360deg);
27 | transform: rotate(360deg);
28 | }
29 | }
30 | body[class*=jconfirm-no-scroll-] {
31 | overflow: hidden !important;
32 | }
33 | .jconfirm {
34 | position: fixed;
35 | top: 0;
36 | left: 0;
37 | right: 0;
38 | bottom: 0;
39 | z-index: 99999999;
40 | font-family: inherit;
41 | overflow: hidden;
42 | }
43 | .jconfirm .jconfirm-bg {
44 | position: fixed;
45 | top: 0;
46 | left: 0;
47 | right: 0;
48 | bottom: 0;
49 | -webkit-transition: opacity .4s;
50 | transition: opacity .4s;
51 | }
52 | .jconfirm .jconfirm-bg.jconfirm-bg-h {
53 | opacity: 0 !important;
54 | }
55 | .jconfirm .jconfirm-scrollpane {
56 | -webkit-perspective: 500px;
57 | perspective: 500px;
58 | -webkit-perspective-origin: center;
59 | perspective-origin: center;
60 | display: table;
61 | width: 100%;
62 | height: 100%;
63 | }
64 | .jconfirm .jconfirm-row {
65 | display: table-row;
66 | width: 100%;
67 | }
68 | .jconfirm .jconfirm-cell {
69 | display: table-cell;
70 | vertical-align: middle;
71 | }
72 | .jconfirm .jconfirm-holder {
73 | max-height: 100%;
74 | padding: 50px 0;
75 | }
76 | .jconfirm .jconfirm-box-container {
77 | -webkit-transition: -webkit-transform;
78 | transition: -webkit-transform;
79 | transition: transform;
80 | transition: transform, -webkit-transform;
81 | }
82 | .jconfirm .jconfirm-box-container.jconfirm-no-transition {
83 | -webkit-transition: none !important;
84 | transition: none !important;
85 | }
86 | .jconfirm .jconfirm-box {
87 | background: white;
88 | border-radius: 4px;
89 | position: relative;
90 | outline: none;
91 | padding: 15px 15px 0;
92 | overflow: hidden;
93 | margin-left: auto;
94 | margin-right: auto;
95 | }
96 | @-webkit-keyframes type-blue {
97 | 1%,
98 | 100% {
99 | border-color: #3498db;
100 | }
101 | 50% {
102 | border-color: #5faee3;
103 | }
104 | }
105 | @keyframes type-blue {
106 | 1%,
107 | 100% {
108 | border-color: #3498db;
109 | }
110 | 50% {
111 | border-color: #5faee3;
112 | }
113 | }
114 | @-webkit-keyframes type-green {
115 | 1%,
116 | 100% {
117 | border-color: #2ecc71;
118 | }
119 | 50% {
120 | border-color: #54d98c;
121 | }
122 | }
123 | @keyframes type-green {
124 | 1%,
125 | 100% {
126 | border-color: #2ecc71;
127 | }
128 | 50% {
129 | border-color: #54d98c;
130 | }
131 | }
132 | @-webkit-keyframes type-red {
133 | 1%,
134 | 100% {
135 | border-color: #e74c3c;
136 | }
137 | 50% {
138 | border-color: #ed7669;
139 | }
140 | }
141 | @keyframes type-red {
142 | 1%,
143 | 100% {
144 | border-color: #e74c3c;
145 | }
146 | 50% {
147 | border-color: #ed7669;
148 | }
149 | }
150 | @-webkit-keyframes type-orange {
151 | 1%,
152 | 100% {
153 | border-color: #f1c40f;
154 | }
155 | 50% {
156 | border-color: #f4d03f;
157 | }
158 | }
159 | @keyframes type-orange {
160 | 1%,
161 | 100% {
162 | border-color: #f1c40f;
163 | }
164 | 50% {
165 | border-color: #f4d03f;
166 | }
167 | }
168 | @-webkit-keyframes type-purple {
169 | 1%,
170 | 100% {
171 | border-color: #9b59b6;
172 | }
173 | 50% {
174 | border-color: #b07cc6;
175 | }
176 | }
177 | @keyframes type-purple {
178 | 1%,
179 | 100% {
180 | border-color: #9b59b6;
181 | }
182 | 50% {
183 | border-color: #b07cc6;
184 | }
185 | }
186 | @-webkit-keyframes type-dark {
187 | 1%,
188 | 100% {
189 | border-color: #34495e;
190 | }
191 | 50% {
192 | border-color: #46627f;
193 | }
194 | }
195 | @keyframes type-dark {
196 | 1%,
197 | 100% {
198 | border-color: #34495e;
199 | }
200 | 50% {
201 | border-color: #46627f;
202 | }
203 | }
204 | .jconfirm .jconfirm-box.jconfirm-type-animated {
205 | -webkit-animation-duration: 2s;
206 | animation-duration: 2s;
207 | -webkit-animation-iteration-count: infinite;
208 | animation-iteration-count: infinite;
209 | }
210 | .jconfirm .jconfirm-box.jconfirm-type-blue {
211 | border-top: solid 7px #3498db;
212 | -webkit-animation-name: type-blue;
213 | animation-name: type-blue;
214 | }
215 | .jconfirm .jconfirm-box.jconfirm-type-green {
216 | border-top: solid 7px #2ecc71;
217 | -webkit-animation-name: type-green;
218 | animation-name: type-green;
219 | }
220 | .jconfirm .jconfirm-box.jconfirm-type-red {
221 | border-top: solid 7px #e74c3c;
222 | -webkit-animation-name: type-red;
223 | animation-name: type-red;
224 | }
225 | .jconfirm .jconfirm-box.jconfirm-type-orange {
226 | border-top: solid 7px #f1c40f;
227 | -webkit-animation-name: type-orange;
228 | animation-name: type-orange;
229 | }
230 | .jconfirm .jconfirm-box.jconfirm-type-purple {
231 | border-top: solid 7px #9b59b6;
232 | -webkit-animation-name: type-purple;
233 | animation-name: type-purple;
234 | }
235 | .jconfirm .jconfirm-box.jconfirm-type-dark {
236 | border-top: solid 7px #34495e;
237 | -webkit-animation-name: type-dark;
238 | animation-name: type-dark;
239 | }
240 | .jconfirm .jconfirm-box.loading {
241 | height: 120px;
242 | }
243 | .jconfirm .jconfirm-box.loading:before {
244 | content: '';
245 | position: absolute;
246 | left: 0;
247 | background: white;
248 | right: 0;
249 | top: 0;
250 | bottom: 0;
251 | border-radius: 10px;
252 | z-index: 1;
253 | }
254 | .jconfirm .jconfirm-box.loading:after {
255 | opacity: 0.6;
256 | content: '';
257 | height: 30px;
258 | width: 30px;
259 | border: solid 3px transparent;
260 | position: absolute;
261 | left: 50%;
262 | margin-left: -15px;
263 | border-radius: 50%;
264 | -webkit-animation: jconfirm-spin 1s infinite linear;
265 | animation: jconfirm-spin 1s infinite linear;
266 | border-bottom-color: dodgerblue;
267 | top: 50%;
268 | margin-top: -15px;
269 | z-index: 2;
270 | }
271 | .jconfirm .jconfirm-box div.jconfirm-closeIcon {
272 | height: 20px;
273 | width: 20px;
274 | position: absolute;
275 | top: 10px;
276 | right: 10px;
277 | cursor: pointer;
278 | opacity: .6;
279 | text-align: center;
280 | font-size: 27px !important;
281 | line-height: 14px !important;
282 | display: none;
283 | z-index: 1;
284 | }
285 | .jconfirm .jconfirm-box div.jconfirm-closeIcon:empty {
286 | display: none;
287 | }
288 | .jconfirm .jconfirm-box div.jconfirm-closeIcon .fa {
289 | font-size: 16px;
290 | }
291 | .jconfirm .jconfirm-box div.jconfirm-closeIcon .glyphicon {
292 | font-size: 16px;
293 | }
294 | .jconfirm .jconfirm-box div.jconfirm-closeIcon .zmdi {
295 | font-size: 16px;
296 | }
297 | .jconfirm .jconfirm-box div.jconfirm-closeIcon:hover {
298 | opacity: 1;
299 | }
300 | .jconfirm .jconfirm-box div.jconfirm-title-c {
301 | display: block;
302 | font-size: 22px;
303 | line-height: 20px;
304 | -webkit-user-select: none;
305 | -moz-user-select: none;
306 | -ms-user-select: none;
307 | user-select: none;
308 | cursor: default;
309 | padding-bottom: 15px;
310 | }
311 | .jconfirm .jconfirm-box div.jconfirm-title-c.jconfirm-hand {
312 | cursor: move;
313 | }
314 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
315 | font-size: inherit;
316 | display: inline-block;
317 | vertical-align: middle;
318 | }
319 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c i {
320 | vertical-align: middle;
321 | }
322 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c:empty {
323 | display: none;
324 | }
325 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-title {
326 | -webkit-user-select: none;
327 | -moz-user-select: none;
328 | -ms-user-select: none;
329 | user-select: none;
330 | font-size: inherit;
331 | font-family: inherit;
332 | display: inline-block;
333 | vertical-align: middle;
334 | }
335 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-title:empty {
336 | display: none;
337 | }
338 | .jconfirm .jconfirm-box div.jconfirm-content-pane {
339 | margin-bottom: 15px;
340 | height: auto;
341 | -webkit-transition: height 0.4s ease-in;
342 | transition: height 0.4s ease-in;
343 | display: inline-block;
344 | width: 100%;
345 | position: relative;
346 | overflow-x: hidden;
347 | overflow-y: auto;
348 | }
349 | .jconfirm .jconfirm-box div.jconfirm-content-pane.no-scroll {
350 | overflow-y: hidden;
351 | }
352 | .jconfirm .jconfirm-box div.jconfirm-content-pane::-webkit-scrollbar {
353 | width: 3px;
354 | }
355 | .jconfirm .jconfirm-box div.jconfirm-content-pane::-webkit-scrollbar-track {
356 | background: rgba(0, 0, 0, 0.1);
357 | }
358 | .jconfirm .jconfirm-box div.jconfirm-content-pane::-webkit-scrollbar-thumb {
359 | background: #666;
360 | border-radius: 3px;
361 | }
362 | .jconfirm .jconfirm-box div.jconfirm-content-pane .jconfirm-content {
363 | overflow: auto;
364 | }
365 | .jconfirm .jconfirm-box div.jconfirm-content-pane .jconfirm-content img {
366 | max-width: 100%;
367 | height: auto;
368 | }
369 | .jconfirm .jconfirm-box div.jconfirm-content-pane .jconfirm-content:empty {
370 | display: none;
371 | }
372 | .jconfirm .jconfirm-box .jconfirm-buttons {
373 | padding-bottom: 11px;
374 | }
375 | .jconfirm .jconfirm-box .jconfirm-buttons > button {
376 | margin-bottom: 4px;
377 | margin-left: 2px;
378 | margin-right: 2px;
379 | }
380 | .jconfirm .jconfirm-box .jconfirm-buttons button {
381 | display: inline-block;
382 | padding: 6px 12px;
383 | font-size: 14px;
384 | font-weight: 400;
385 | line-height: 1.42857143;
386 | text-align: center;
387 | white-space: nowrap;
388 | vertical-align: middle;
389 | -ms-touch-action: manipulation;
390 | touch-action: manipulation;
391 | cursor: pointer;
392 | -webkit-user-select: none;
393 | -moz-user-select: none;
394 | -ms-user-select: none;
395 | user-select: none;
396 | border-radius: 4px;
397 | min-height: 1em;
398 | -webkit-transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, background 0.1s ease, -webkit-box-shadow 0.1s ease;
399 | transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, background 0.1s ease, -webkit-box-shadow 0.1s ease;
400 | transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
401 | transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease, -webkit-box-shadow 0.1s ease;
402 | -webkit-tap-highlight-color: transparent;
403 | border: none;
404 | background-image: none;
405 | }
406 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-blue {
407 | background-color: #3498db;
408 | color: #FFF;
409 | text-shadow: none;
410 | -webkit-transition: background .2s;
411 | transition: background .2s;
412 | }
413 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-blue:hover {
414 | background-color: #2980b9;
415 | color: #FFF;
416 | }
417 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-green {
418 | background-color: #2ecc71;
419 | color: #FFF;
420 | text-shadow: none;
421 | -webkit-transition: background .2s;
422 | transition: background .2s;
423 | }
424 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-green:hover {
425 | background-color: #27ae60;
426 | color: #FFF;
427 | }
428 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-red {
429 | background-color: #e74c3c;
430 | color: #FFF;
431 | text-shadow: none;
432 | -webkit-transition: background .2s;
433 | transition: background .2s;
434 | }
435 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-red:hover {
436 | background-color: #c0392b;
437 | color: #FFF;
438 | }
439 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-orange {
440 | background-color: #f1c40f;
441 | color: #FFF;
442 | text-shadow: none;
443 | -webkit-transition: background .2s;
444 | transition: background .2s;
445 | }
446 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-orange:hover {
447 | background-color: #f39c12;
448 | color: #FFF;
449 | }
450 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-default {
451 | background-color: #ecf0f1;
452 | color: #000;
453 | text-shadow: none;
454 | -webkit-transition: background .2s;
455 | transition: background .2s;
456 | }
457 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-default:hover {
458 | background-color: #bdc3c7;
459 | color: #000;
460 | }
461 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-purple {
462 | background-color: #9b59b6;
463 | color: #FFF;
464 | text-shadow: none;
465 | -webkit-transition: background .2s;
466 | transition: background .2s;
467 | }
468 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-purple:hover {
469 | background-color: #8e44ad;
470 | color: #FFF;
471 | }
472 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-dark {
473 | background-color: #34495e;
474 | color: #FFF;
475 | text-shadow: none;
476 | -webkit-transition: background .2s;
477 | transition: background .2s;
478 | }
479 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-dark:hover {
480 | background-color: #2c3e50;
481 | color: #FFF;
482 | }
483 | .jconfirm .jconfirm-box.jconfirm-type-red .jconfirm-title-c .jconfirm-icon-c {
484 | color: #e74c3c !important;
485 | }
486 | .jconfirm .jconfirm-box.jconfirm-type-blue .jconfirm-title-c .jconfirm-icon-c {
487 | color: #3498db !important;
488 | }
489 | .jconfirm .jconfirm-box.jconfirm-type-green .jconfirm-title-c .jconfirm-icon-c {
490 | color: #2ecc71 !important;
491 | }
492 | .jconfirm .jconfirm-box.jconfirm-type-purple .jconfirm-title-c .jconfirm-icon-c {
493 | color: #9b59b6 !important;
494 | }
495 | .jconfirm .jconfirm-box.jconfirm-type-orange .jconfirm-title-c .jconfirm-icon-c {
496 | color: #f1c40f !important;
497 | }
498 | .jconfirm .jconfirm-box.jconfirm-type-dark .jconfirm-title-c .jconfirm-icon-c {
499 | color: #34495e !important;
500 | }
501 | .jconfirm .jconfirm-clear {
502 | clear: both;
503 | }
504 | .jconfirm.jconfirm-rtl {
505 | direction: rtl;
506 | }
507 | .jconfirm.jconfirm-rtl div.jconfirm-closeIcon {
508 | left: 5px;
509 | right: auto;
510 | }
511 | .jconfirm.jconfirm-white .jconfirm-bg,
512 | .jconfirm.jconfirm-light .jconfirm-bg {
513 | background-color: #444;
514 | opacity: .2;
515 | }
516 | .jconfirm.jconfirm-white .jconfirm-box,
517 | .jconfirm.jconfirm-light .jconfirm-box {
518 | -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
519 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
520 | border-radius: 5px;
521 | }
522 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-title-c .jconfirm-icon-c,
523 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
524 | margin-right: 8px;
525 | margin-left: 0px;
526 | }
527 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons,
528 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons {
529 | float: right;
530 | }
531 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons button,
532 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons button {
533 | text-transform: uppercase;
534 | font-size: 14px;
535 | font-weight: bold;
536 | text-shadow: none;
537 | }
538 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons button.btn-default,
539 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons button.btn-default {
540 | -webkit-box-shadow: none;
541 | box-shadow: none;
542 | color: #333;
543 | }
544 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons button.btn-default:hover,
545 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons button.btn-default:hover {
546 | background: #ddd;
547 | }
548 | .jconfirm.jconfirm-white.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c,
549 | .jconfirm.jconfirm-light.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
550 | margin-left: 8px;
551 | margin-right: 0px;
552 | }
553 | .jconfirm.jconfirm-black .jconfirm-bg,
554 | .jconfirm.jconfirm-dark .jconfirm-bg {
555 | background-color: darkslategray;
556 | opacity: .4;
557 | }
558 | .jconfirm.jconfirm-black .jconfirm-box,
559 | .jconfirm.jconfirm-dark .jconfirm-box {
560 | -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
561 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
562 | background: #444;
563 | border-radius: 5px;
564 | color: white;
565 | }
566 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-title-c .jconfirm-icon-c,
567 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
568 | margin-right: 8px;
569 | margin-left: 0px;
570 | }
571 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons,
572 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons {
573 | float: right;
574 | }
575 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons button,
576 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons button {
577 | border: none;
578 | background-image: none;
579 | text-transform: uppercase;
580 | font-size: 14px;
581 | font-weight: bold;
582 | text-shadow: none;
583 | -webkit-transition: background .1s;
584 | transition: background .1s;
585 | color: white;
586 | }
587 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons button.btn-default,
588 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons button.btn-default {
589 | -webkit-box-shadow: none;
590 | box-shadow: none;
591 | color: #fff;
592 | background: none;
593 | }
594 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons button.btn-default:hover,
595 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons button.btn-default:hover {
596 | background: #666;
597 | }
598 | .jconfirm.jconfirm-black.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c,
599 | .jconfirm.jconfirm-dark.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
600 | margin-left: 8px;
601 | margin-right: 0px;
602 | }
603 | .jconfirm .jconfirm-box.hilight.jconfirm-hilight-shake {
604 | -webkit-animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
605 | animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
606 | -webkit-transform: translate3d(0, 0, 0);
607 | transform: translate3d(0, 0, 0);
608 | }
609 | .jconfirm .jconfirm-box.hilight.jconfirm-hilight-glow {
610 | -webkit-animation: glow 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
611 | animation: glow 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
612 | -webkit-transform: translate3d(0, 0, 0);
613 | transform: translate3d(0, 0, 0);
614 | }
615 | @-webkit-keyframes shake {
616 | 10%,
617 | 90% {
618 | -webkit-transform: translate3d(-2px, 0, 0);
619 | transform: translate3d(-2px, 0, 0);
620 | }
621 | 20%,
622 | 80% {
623 | -webkit-transform: translate3d(4px, 0, 0);
624 | transform: translate3d(4px, 0, 0);
625 | }
626 | 30%,
627 | 50%,
628 | 70% {
629 | -webkit-transform: translate3d(-8px, 0, 0);
630 | transform: translate3d(-8px, 0, 0);
631 | }
632 | 40%,
633 | 60% {
634 | -webkit-transform: translate3d(8px, 0, 0);
635 | transform: translate3d(8px, 0, 0);
636 | }
637 | }
638 | @keyframes shake {
639 | 10%,
640 | 90% {
641 | -webkit-transform: translate3d(-2px, 0, 0);
642 | transform: translate3d(-2px, 0, 0);
643 | }
644 | 20%,
645 | 80% {
646 | -webkit-transform: translate3d(4px, 0, 0);
647 | transform: translate3d(4px, 0, 0);
648 | }
649 | 30%,
650 | 50%,
651 | 70% {
652 | -webkit-transform: translate3d(-8px, 0, 0);
653 | transform: translate3d(-8px, 0, 0);
654 | }
655 | 40%,
656 | 60% {
657 | -webkit-transform: translate3d(8px, 0, 0);
658 | transform: translate3d(8px, 0, 0);
659 | }
660 | }
661 | @-webkit-keyframes glow {
662 | 0%,
663 | 100% {
664 | -webkit-box-shadow: 0 0 0px red;
665 | box-shadow: 0 0 0px red;
666 | }
667 | 50% {
668 | -webkit-box-shadow: 0 0 30px red;
669 | box-shadow: 0 0 30px red;
670 | }
671 | }
672 | @keyframes glow {
673 | 0%,
674 | 100% {
675 | -webkit-box-shadow: 0 0 0px red;
676 | box-shadow: 0 0 0px red;
677 | }
678 | 50% {
679 | -webkit-box-shadow: 0 0 30px red;
680 | box-shadow: 0 0 30px red;
681 | }
682 | }
683 | /*Transition rules*/
684 | .jconfirm {
685 | -webkit-perspective: 400px;
686 | perspective: 400px;
687 | }
688 | .jconfirm .jconfirm-box {
689 | opacity: 1;
690 | -webkit-transition-property: all;
691 | transition-property: all;
692 | }
693 | .jconfirm .jconfirm-box.jconfirm-animation-top,
694 | .jconfirm .jconfirm-box.jconfirm-animation-left,
695 | .jconfirm .jconfirm-box.jconfirm-animation-right,
696 | .jconfirm .jconfirm-box.jconfirm-animation-bottom,
697 | .jconfirm .jconfirm-box.jconfirm-animation-opacity,
698 | .jconfirm .jconfirm-box.jconfirm-animation-zoom,
699 | .jconfirm .jconfirm-box.jconfirm-animation-scale,
700 | .jconfirm .jconfirm-box.jconfirm-animation-none,
701 | .jconfirm .jconfirm-box.jconfirm-animation-rotate,
702 | .jconfirm .jconfirm-box.jconfirm-animation-rotatex,
703 | .jconfirm .jconfirm-box.jconfirm-animation-rotatey,
704 | .jconfirm .jconfirm-box.jconfirm-animation-scaley,
705 | .jconfirm .jconfirm-box.jconfirm-animation-scalex {
706 | opacity: 0;
707 | }
708 | .jconfirm .jconfirm-box.jconfirm-animation-rotate {
709 | -webkit-transform: rotate(90deg);
710 | transform: rotate(90deg);
711 | }
712 | .jconfirm .jconfirm-box.jconfirm-animation-rotatex {
713 | -webkit-transform: rotateX(90deg);
714 | transform: rotateX(90deg);
715 | -webkit-transform-origin: center;
716 | transform-origin: center;
717 | }
718 | .jconfirm .jconfirm-box.jconfirm-animation-rotatexr {
719 | -webkit-transform: rotateX(-90deg);
720 | transform: rotateX(-90deg);
721 | -webkit-transform-origin: center;
722 | transform-origin: center;
723 | }
724 | .jconfirm .jconfirm-box.jconfirm-animation-rotatey {
725 | -webkit-transform: rotatey(90deg);
726 | transform: rotatey(90deg);
727 | -webkit-transform-origin: center;
728 | transform-origin: center;
729 | }
730 | .jconfirm .jconfirm-box.jconfirm-animation-rotateyr {
731 | -webkit-transform: rotatey(-90deg);
732 | transform: rotatey(-90deg);
733 | -webkit-transform-origin: center;
734 | transform-origin: center;
735 | }
736 | .jconfirm .jconfirm-box.jconfirm-animation-scaley {
737 | -webkit-transform: scaley(1.5);
738 | transform: scaley(1.5);
739 | -webkit-transform-origin: center;
740 | transform-origin: center;
741 | }
742 | .jconfirm .jconfirm-box.jconfirm-animation-scalex {
743 | -webkit-transform: scalex(1.5);
744 | transform: scalex(1.5);
745 | -webkit-transform-origin: center;
746 | transform-origin: center;
747 | }
748 | .jconfirm .jconfirm-box.jconfirm-animation-top {
749 | -webkit-transform: translate(0px, -100px);
750 | transform: translate(0px, -100px);
751 | }
752 | .jconfirm .jconfirm-box.jconfirm-animation-left {
753 | -webkit-transform: translate(-100px, 0px);
754 | transform: translate(-100px, 0px);
755 | }
756 | .jconfirm .jconfirm-box.jconfirm-animation-right {
757 | -webkit-transform: translate(100px, 0px);
758 | transform: translate(100px, 0px);
759 | }
760 | .jconfirm .jconfirm-box.jconfirm-animation-bottom {
761 | -webkit-transform: translate(0px, 100px);
762 | transform: translate(0px, 100px);
763 | }
764 | .jconfirm .jconfirm-box.jconfirm-animation-zoom {
765 | -webkit-transform: scale(1.2);
766 | transform: scale(1.2);
767 | }
768 | .jconfirm .jconfirm-box.jconfirm-animation-scale {
769 | -webkit-transform: scale(0.5);
770 | transform: scale(0.5);
771 | }
772 | .jconfirm .jconfirm-box.jconfirm-animation-none {
773 | visibility: hidden;
774 | }
775 | .jconfirm.jconfirm-supervan .jconfirm-bg {
776 | background-color: rgba(54, 70, 93, 0.95);
777 | }
778 | .jconfirm.jconfirm-supervan .jconfirm-box {
779 | background-color: transparent;
780 | }
781 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-blue {
782 | border: none;
783 | }
784 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-green {
785 | border: none;
786 | }
787 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-red {
788 | border: none;
789 | }
790 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-orange {
791 | border: none;
792 | }
793 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-purple {
794 | border: none;
795 | }
796 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-dark {
797 | border: none;
798 | }
799 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-closeIcon {
800 | color: white;
801 | }
802 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-title-c {
803 | text-align: center;
804 | color: white;
805 | font-size: 28px;
806 | font-weight: normal;
807 | }
808 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-title-c > * {
809 | padding-bottom: 25px;
810 | }
811 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
812 | margin-right: 8px;
813 | margin-left: 0px;
814 | }
815 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-content-pane {
816 | margin-bottom: 25px;
817 | }
818 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-content {
819 | text-align: center;
820 | color: white;
821 | }
822 | .jconfirm.jconfirm-supervan .jconfirm-box .jconfirm-buttons {
823 | text-align: center;
824 | }
825 | .jconfirm.jconfirm-supervan .jconfirm-box .jconfirm-buttons button {
826 | font-size: 16px;
827 | border-radius: 2px;
828 | background: #303f53;
829 | text-shadow: none;
830 | border: none;
831 | color: white;
832 | padding: 10px;
833 | min-width: 100px;
834 | }
835 | .jconfirm.jconfirm-supervan.jconfirm-rtl .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
836 | margin-left: 8px;
837 | margin-right: 0px;
838 | }
839 | .jconfirm.jconfirm-material .jconfirm-bg {
840 | background-color: rgba(0, 0, 0, 0.67);
841 | }
842 | .jconfirm.jconfirm-material .jconfirm-box {
843 | background-color: white;
844 | -webkit-box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
845 | box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
846 | padding: 30px 25px 10px 25px;
847 | }
848 | .jconfirm.jconfirm-material .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
849 | margin-right: 8px;
850 | margin-left: 0px;
851 | }
852 | .jconfirm.jconfirm-material .jconfirm-box div.jconfirm-closeIcon {
853 | color: rgba(0, 0, 0, 0.87);
854 | }
855 | .jconfirm.jconfirm-material .jconfirm-box div.jconfirm-title-c {
856 | color: rgba(0, 0, 0, 0.87);
857 | font-size: 22px;
858 | font-weight: bold;
859 | }
860 | .jconfirm.jconfirm-material .jconfirm-box div.jconfirm-content {
861 | color: rgba(0, 0, 0, 0.87);
862 | }
863 | .jconfirm.jconfirm-material .jconfirm-box .jconfirm-buttons {
864 | text-align: right;
865 | }
866 | .jconfirm.jconfirm-material .jconfirm-box .jconfirm-buttons button {
867 | text-transform: uppercase;
868 | font-weight: 500;
869 | }
870 | .jconfirm.jconfirm-material.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
871 | margin-left: 8px;
872 | margin-right: 0px;
873 | }
874 | .jconfirm.jconfirm-bootstrap .jconfirm-bg {
875 | background-color: rgba(0, 0, 0, 0.21);
876 | }
877 | .jconfirm.jconfirm-bootstrap .jconfirm-box {
878 | background-color: white;
879 | -webkit-box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.2);
880 | box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.2);
881 | border: solid 1px rgba(0, 0, 0, 0.4);
882 | padding: 15px 0 0;
883 | }
884 | .jconfirm.jconfirm-bootstrap .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
885 | margin-right: 8px;
886 | margin-left: 0px;
887 | }
888 | .jconfirm.jconfirm-bootstrap .jconfirm-box div.jconfirm-closeIcon {
889 | color: rgba(0, 0, 0, 0.87);
890 | }
891 | .jconfirm.jconfirm-bootstrap .jconfirm-box div.jconfirm-title-c {
892 | color: rgba(0, 0, 0, 0.87);
893 | font-size: 22px;
894 | font-weight: bold;
895 | padding-left: 15px;
896 | padding-right: 15px;
897 | }
898 | .jconfirm.jconfirm-bootstrap .jconfirm-box div.jconfirm-content {
899 | color: rgba(0, 0, 0, 0.87);
900 | padding: 0px 15px;
901 | }
902 | .jconfirm.jconfirm-bootstrap .jconfirm-box .jconfirm-buttons {
903 | text-align: right;
904 | padding: 10px;
905 | margin: -5px 0 0px;
906 | border-top: solid 1px #ddd;
907 | overflow: hidden;
908 | border-radius: 0 0 4px 4px;
909 | }
910 | .jconfirm.jconfirm-bootstrap .jconfirm-box .jconfirm-buttons button {
911 | font-weight: 500;
912 | }
913 | .jconfirm.jconfirm-bootstrap.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
914 | margin-left: 8px;
915 | margin-right: 0px;
916 | }
917 | .jconfirm.jconfirm-modern .jconfirm-bg {
918 | background-color: slategray;
919 | opacity: .6;
920 | }
921 | .jconfirm.jconfirm-modern .jconfirm-box {
922 | background-color: white;
923 | -webkit-box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
924 | box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
925 | padding: 30px 30px 15px;
926 | }
927 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-closeIcon {
928 | color: rgba(0, 0, 0, 0.87);
929 | top: 15px;
930 | right: 15px;
931 | }
932 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-title-c {
933 | color: rgba(0, 0, 0, 0.87);
934 | font-size: 24px;
935 | font-weight: bold;
936 | text-align: center;
937 | margin-bottom: 10px;
938 | }
939 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
940 | -webkit-transition: -webkit-transform .5s;
941 | transition: -webkit-transform .5s;
942 | transition: transform .5s;
943 | transition: transform .5s, -webkit-transform .5s;
944 | -webkit-transform: scale(0);
945 | transform: scale(0);
946 | display: block;
947 | margin-right: 0px;
948 | margin-left: 0px;
949 | margin-bottom: 10px;
950 | font-size: 69px;
951 | color: #aaa;
952 | }
953 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-content {
954 | text-align: center;
955 | font-size: 15px;
956 | color: #777;
957 | margin-bottom: 25px;
958 | }
959 | .jconfirm.jconfirm-modern .jconfirm-box .jconfirm-buttons {
960 | text-align: center;
961 | }
962 | .jconfirm.jconfirm-modern .jconfirm-box .jconfirm-buttons button {
963 | font-weight: bold;
964 | text-transform: uppercase;
965 | -webkit-transition: background .1s;
966 | transition: background .1s;
967 | padding: 10px 20px;
968 | }
969 | .jconfirm.jconfirm-modern .jconfirm-box .jconfirm-buttons button + button {
970 | margin-left: 4px;
971 | }
972 | .jconfirm.jconfirm-modern.jconfirm-open .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
973 | -webkit-transform: scale(1);
974 | transform: scale(1);
975 | }
976 |
--------------------------------------------------------------------------------
/addons/whmcspf/static/css/jquery-confirm.less:
--------------------------------------------------------------------------------
1 | /*!
2 | * jquery-confirm v3.3.0 (http://craftpip.github.io/jquery-confirm/)
3 | * Author: boniface pereira
4 | * Website: www.craftpip.com
5 | * Contact: hey@craftpip.com
6 | *
7 | * Copyright 2013-2017 jquery-confirm
8 | * Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
9 | */
10 | @blue: #3498db;
11 | @blueHover: #2980b9;
12 | @green: #2ecc71;
13 | @greenHover: #27ae60;
14 | @red: #e74c3c;
15 | @redHover: #c0392b;
16 | @orange: #f1c40f;
17 | @orangeHover: #f39c12;
18 | @purple: #9b59b6;
19 | @purpleHover: #8e44ad;
20 | @default: #ecf0f1;
21 | @defaultHover: #bdc3c7;
22 | @dark: #34495e;
23 | @darkHover: #2c3e50;
24 |
25 | @keyframes jconfirm-spin {
26 | from {
27 | transform: rotate(0deg);
28 | }
29 | to {
30 | transform: rotate(360deg);
31 | }
32 | }
33 |
34 | body[class*=jconfirm-no-scroll-] {
35 | overflow: hidden !important;
36 | }
37 |
38 | .jconfirm {
39 | position: fixed;
40 | top: 0;
41 | left: 0;
42 | right: 0;
43 | bottom: 0;
44 | z-index: 99999999;
45 | font-family: inherit;
46 | overflow: hidden;
47 |
48 | .jconfirm-bg {
49 | position: fixed;
50 | top: 0;
51 | left: 0;
52 | right: 0;
53 | bottom: 0;
54 | transition: opacity .4s;
55 |
56 | &.jconfirm-bg-h {
57 | opacity: 0 !important;
58 | }
59 | }
60 | .jconfirm-scrollpane {
61 | //overflow-y: auto;
62 | perspective: 500px;
63 | perspective-origin: center;
64 |
65 | display: table;
66 | width: 100%;
67 | height: 100%;
68 | }
69 | .jconfirm-row {
70 | display: table-row;
71 | width: 100%;
72 | }
73 | .jconfirm-cell {
74 | //height: 100%;
75 | display: table-cell;
76 | vertical-align: middle;
77 | }
78 | .jconfirm-holder {
79 | max-height: 100%;
80 | padding: 50px 0;
81 | }
82 | .jconfirm-box-container {
83 | transition: transform;
84 |
85 | &.jconfirm-no-transition {
86 | transition: none !important;
87 | }
88 | }
89 | .jconfirm-box {
90 | background: white;
91 | border-radius: 4px;
92 | position: relative;
93 | outline: none;
94 | padding: 15px 15px 0;
95 | overflow: hidden;
96 | margin-left: auto;
97 | margin-right: auto;
98 |
99 | @keyframes type-blue {
100 | 1%, 100% {
101 | border-color: @blue;
102 | }
103 | 50% {
104 | border-color: lighten(@blue, 10%);
105 | }
106 | }
107 | @keyframes type-green {
108 | 1%, 100% {
109 | border-color: @green;
110 | }
111 | 50% {
112 | border-color: lighten(@green, 10%);
113 | }
114 | }
115 | @keyframes type-red {
116 | 1%, 100% {
117 | border-color: @red;
118 | }
119 | 50% {
120 | border-color: lighten(@red, 10%);
121 | }
122 | }
123 | @keyframes type-orange {
124 | 1%, 100% {
125 | border-color: @orange;
126 | }
127 | 50% {
128 | border-color: lighten(@orange, 10%);
129 | }
130 | }
131 | @keyframes type-purple {
132 | 1%, 100% {
133 | border-color: @purple;
134 | }
135 | 50% {
136 | border-color: lighten(@purple, 10%);
137 | }
138 | }
139 | @keyframes type-dark {
140 | 1%, 100% {
141 | border-color: @dark;
142 | }
143 | 50% {
144 | border-color: lighten(@dark, 10%);
145 | }
146 | }
147 | &.jconfirm-type-animated {
148 | animation-duration: 2s;
149 | animation-iteration-count: infinite;
150 | }
151 | &.jconfirm-type-blue {
152 | border-top: solid 7px @blue;
153 | animation-name: type-blue;
154 | }
155 | &.jconfirm-type-green {
156 | border-top: solid 7px @green;
157 | animation-name: type-green;
158 | }
159 | &.jconfirm-type-red {
160 | border-top: solid 7px @red;
161 | animation-name: type-red;
162 | }
163 | &.jconfirm-type-orange {
164 | border-top: solid 7px @orange;
165 | animation-name: type-orange;
166 | }
167 | &.jconfirm-type-purple {
168 | border-top: solid 7px @purple;
169 | animation-name: type-purple;
170 | }
171 | &.jconfirm-type-dark {
172 | border-top: solid 7px @dark;
173 | animation-name: type-dark;
174 | }
175 | &.loading {
176 | height: 120px;
177 |
178 | &:before {
179 | content: '';
180 | position: absolute;
181 | left: 0;
182 | background: white;
183 | right: 0;
184 | top: 0;
185 | bottom: 0;
186 | border-radius: 10px;
187 | z-index: 1;
188 | }
189 | &:after {
190 | opacity: 0.6;
191 | content: '';
192 | height: 30px;
193 | width: 30px;
194 | border: solid 3px transparent;
195 | position: absolute;
196 | left: 50%;
197 | margin-left: -15px;
198 | border-radius: 50%;
199 | animation: jconfirm-spin 1s infinite linear;
200 | border-bottom-color: dodgerblue;
201 | top: 50%;
202 | margin-top: -15px;
203 | z-index: 2;
204 | }
205 | }
206 |
207 | div.jconfirm-closeIcon {
208 | height: 20px;
209 | width: 20px;
210 | position: absolute;
211 | top: 10px;
212 | right: 10px;
213 | cursor: pointer;
214 | opacity: .6;
215 | text-align: center;
216 | font-size: 27px !important;
217 | line-height: 14px !important;
218 | display: none;
219 | z-index: 1;
220 |
221 | &:empty {
222 | display: none;
223 | }
224 |
225 | .fa {
226 | font-size: 16px;
227 | }
228 | .glyphicon {
229 | font-size: 16px;
230 | }
231 | .zmdi {
232 | font-size: 16px;
233 | }
234 |
235 | &:hover {
236 | opacity: 1;
237 | }
238 | }
239 | div.jconfirm-title-c {
240 | display: block;
241 | font-size: 22px;
242 | line-height: 20px;
243 | user-select: none;
244 | cursor: default;
245 | padding-bottom: 15px;
246 |
247 | &.jconfirm-hand {
248 | cursor: move;
249 | }
250 | .jconfirm-icon-c {
251 | font-size: inherit;
252 | //padding-bottom: 15px;
253 | display: inline-block;
254 | vertical-align: middle;
255 | i {
256 | vertical-align: middle;
257 | }
258 | &:empty {
259 | display: none;
260 | }
261 | }
262 | .jconfirm-title {
263 | user-select: none;
264 | font-size: inherit;
265 | font-family: inherit;
266 | display: inline-block;
267 | vertical-align: middle;
268 | //padding-bottom: 15px;
269 | &:empty {
270 | display: none;
271 | }
272 | }
273 | }
274 |
275 | div.jconfirm-content-pane {
276 | margin-bottom: 15px;
277 | height: auto;
278 | transition: height .4s ease-in;
279 | display: inline-block;
280 | width: 100%;
281 | position: relative;
282 | overflow-x: hidden;
283 | overflow-y: auto;
284 |
285 | &.no-scroll {
286 | overflow-y: hidden;
287 | }
288 | &::-webkit-scrollbar {
289 | width: 3px;
290 | }
291 |
292 | &::-webkit-scrollbar-track {
293 | background: rgba(0, 0, 0, .1);
294 | }
295 |
296 | &::-webkit-scrollbar-thumb {
297 | background: #666;
298 | border-radius: 3px;
299 | }
300 |
301 | .jconfirm-content {
302 | overflow: auto;
303 |
304 | img {
305 | max-width: 100%;
306 | height: auto;
307 | }
308 | &:empty {
309 | display: none;
310 | }
311 | }
312 | }
313 |
314 | .jconfirm-buttons {
315 | padding-bottom: 11px;
316 | > button {
317 | margin-bottom: 4px;
318 | margin-left: 2px;
319 | margin-right: 2px;
320 | }
321 |
322 | button {
323 | display: inline-block;
324 | padding: 6px 12px;
325 | font-size: 14px;
326 | font-weight: 400;
327 | line-height: 1.42857143;
328 | text-align: center;
329 | white-space: nowrap;
330 | vertical-align: middle;
331 | -ms-touch-action: manipulation;
332 | touch-action: manipulation;
333 | cursor: pointer;
334 | -webkit-user-select: none;
335 | -moz-user-select: none;
336 | -ms-user-select: none;
337 | user-select: none;
338 | border-radius: 4px;
339 | min-height: 1em;
340 | //outline: blue;
341 | //user-select: none;
342 | transition: opacity .1s ease, background-color .1s ease, color .1s ease, box-shadow .1s ease, background .1s ease;
343 | -webkit-tap-highlight-color: transparent;
344 | border: none;
345 | background-image: none;
346 |
347 | &.btn-blue {
348 | background-color: @blue;
349 | color: #FFF;
350 | text-shadow: none;
351 | transition: background .2s;
352 | &:hover {
353 | background-color: @blueHover;
354 | color: #FFF;
355 | }
356 | }
357 |
358 | &.btn-green {
359 | background-color: @green;
360 | color: #FFF;
361 | text-shadow: none;
362 | transition: background .2s;
363 | &:hover {
364 | background-color: @greenHover;
365 | color: #FFF;
366 | }
367 | }
368 |
369 | &.btn-red {
370 | background-color: @red;
371 | color: #FFF;
372 | text-shadow: none;
373 | transition: background .2s;
374 | &:hover {
375 | background-color: @redHover;
376 | color: #FFF;
377 | }
378 | }
379 |
380 | &.btn-orange {
381 | background-color: @orange;
382 | color: #FFF;
383 | text-shadow: none;
384 | transition: background .2s;
385 | &:hover {
386 | background-color: @orangeHover;
387 | color: #FFF;
388 | }
389 | }
390 |
391 | &.btn-default {
392 | background-color: @default;
393 | color: #000;
394 | text-shadow: none;
395 | transition: background .2s;
396 | &:hover {
397 | background-color: @defaultHover;
398 | color: #000;
399 | }
400 | }
401 |
402 | &.btn-purple {
403 | background-color: @purple;
404 | color: #FFF;
405 | text-shadow: none;
406 | transition: background .2s;
407 | &:hover {
408 | background-color: @purpleHover;
409 | color: #FFF;
410 | }
411 | }
412 |
413 | &.btn-dark {
414 | background-color: @dark;
415 | color: #FFF;
416 | text-shadow: none;
417 | transition: background .2s;
418 | &:hover {
419 | background-color: @darkHover;
420 | color: #FFF;
421 | }
422 | }
423 | }
424 | }
425 |
426 | &.jconfirm-type-red .jconfirm-title-c .jconfirm-icon-c {
427 | color: @red !important;
428 | }
429 | &.jconfirm-type-blue .jconfirm-title-c .jconfirm-icon-c {
430 | color: @blue !important;
431 | }
432 | &.jconfirm-type-green .jconfirm-title-c .jconfirm-icon-c {
433 | color: @green !important;
434 | }
435 | &.jconfirm-type-purple .jconfirm-title-c .jconfirm-icon-c {
436 | color: @purple !important;
437 | }
438 | &.jconfirm-type-orange .jconfirm-title-c .jconfirm-icon-c {
439 | color: @orange !important;
440 | }
441 | &.jconfirm-type-dark .jconfirm-title-c .jconfirm-icon-c {
442 | color: @dark !important;
443 | }
444 | }
445 |
446 | .jconfirm-clear {
447 | clear: both;
448 | }
449 |
450 | &.jconfirm-rtl {
451 | direction: rtl;
452 | div.jconfirm-closeIcon {
453 | left: 5px;
454 | right: auto;
455 | }
456 | }
457 |
458 | &.jconfirm-white, &.jconfirm-light {
459 | .jconfirm-bg {
460 | background-color: #444;
461 | opacity: .2;
462 | }
463 | .jconfirm-box {
464 | box-shadow: 0 2px 6px rgba(0, 0, 0, .2);
465 | border-radius: 5px;
466 |
467 | .jconfirm-title-c .jconfirm-icon-c {
468 | margin-right: 8px;
469 | margin-left: 0px;
470 | }
471 | .jconfirm-buttons {
472 | float: right;
473 |
474 | button {
475 | text-transform: uppercase;
476 | font-size: 14px;
477 | font-weight: bold;
478 | text-shadow: none;
479 | }
480 | button.btn-default {
481 | box-shadow: none;
482 | color: #333;
483 |
484 | &:hover {
485 | background: #ddd;
486 | }
487 | }
488 | }
489 | }
490 | &.jconfirm-rtl {
491 | .jconfirm-title-c .jconfirm-icon-c {
492 | margin-left: 8px;
493 | margin-right: 0px;
494 | }
495 | }
496 | }
497 |
498 | &.jconfirm-black, &.jconfirm-dark {
499 | .jconfirm-bg {
500 | background-color: darkslategray;
501 | opacity: .4;
502 | }
503 | .jconfirm-box {
504 | box-shadow: 0 2px 6px rgba(0, 0, 0, .2);
505 | background: #444;
506 | border-radius: 5px;
507 | color: white;
508 |
509 | .jconfirm-title-c .jconfirm-icon-c {
510 | margin-right: 8px;
511 | margin-left: 0px;
512 | }
513 |
514 | .jconfirm-buttons {
515 | float: right;
516 |
517 | button {
518 | border: none;
519 | background-image: none;
520 | text-transform: uppercase;
521 | font-size: 14px;
522 | font-weight: bold;
523 | text-shadow: none;
524 | transition: background .1s;
525 | color: white;
526 | }
527 | button.btn-default {
528 | box-shadow: none;
529 | color: #fff;
530 | background: none;
531 |
532 | &:hover {
533 | background: #666;
534 | }
535 | }
536 | }
537 | }
538 |
539 | &.jconfirm-rtl {
540 | .jconfirm-title-c .jconfirm-icon-c {
541 | margin-left: 8px;
542 | margin-right: 0px;
543 | }
544 | }
545 | }
546 |
547 | .jconfirm-box.hilight {
548 | &.jconfirm-hilight-shake {
549 | animation: shake 0.82s cubic-bezier(.36, .07, .19, .97) both;
550 | transform: translate3d(0, 0, 0);
551 | }
552 | &.jconfirm-hilight-glow {
553 | animation: glow 0.82s cubic-bezier(.36, .07, .19, .97) both;
554 | transform: translate3d(0, 0, 0);
555 | }
556 | }
557 | }
558 |
559 | @keyframes shake {
560 | 10%, 90% {
561 | transform: translate3d(-2px, 0, 0);
562 | }
563 | 20%, 80% {
564 | transform: translate3d(4px, 0, 0);
565 | }
566 | 30%, 50%, 70% {
567 | transform: translate3d(-8px, 0, 0);
568 | }
569 | 40%, 60% {
570 | transform: translate3d(8px, 0, 0);
571 | }
572 | }
573 |
574 | @keyframes glow {
575 | 0%, 100% {
576 | box-shadow: 0 0 0px red;
577 | }
578 | 50% {
579 | box-shadow: 0 0 30px red;
580 | }
581 | }
582 |
583 | /*Transition rules*/
584 | .jconfirm {
585 | perspective: 400px;
586 |
587 | .jconfirm-box {
588 | opacity: 1;
589 | transition-property: all;
590 |
591 | &.jconfirm-animation-top, &.jconfirm-animation-left, &.jconfirm-animation-right, &.jconfirm-animation-bottom, &.jconfirm-animation-opacity, &.jconfirm-animation-zoom, &.jconfirm-animation-scale, &.jconfirm-animation-none, &.jconfirm-animation-rotate, &.jconfirm-animation-rotatex, &.jconfirm-animation-rotatey, &.jconfirm-animation-scaley, &.jconfirm-animation-scalex {
592 | opacity: 0;
593 | }
594 | &.jconfirm-animation-rotate {
595 | transform: rotate(90deg);
596 | }
597 | &.jconfirm-animation-rotatex {
598 | transform: rotateX(90deg);
599 | transform-origin: center;
600 | }
601 | &.jconfirm-animation-rotatexr {
602 | transform: rotateX(-90deg);
603 | transform-origin: center;
604 | }
605 | &.jconfirm-animation-rotatey {
606 | transform: rotatey(90deg);
607 | transform-origin: center;
608 | }
609 | &.jconfirm-animation-rotateyr {
610 | transform: rotatey(-90deg);
611 | transform-origin: center;
612 | }
613 | &.jconfirm-animation-scaley {
614 | transform: scaley(1.5);
615 | transform-origin: center;
616 | }
617 | &.jconfirm-animation-scalex {
618 | transform: scalex(1.5);
619 | transform-origin: center;
620 | }
621 | &.jconfirm-animation-top {
622 | transform: translate(0px, -100px);
623 | }
624 | &.jconfirm-animation-left {
625 | transform: translate(-100px, 0px);
626 | }
627 | &.jconfirm-animation-right {
628 | transform: translate(100px, 0px);
629 | }
630 | &.jconfirm-animation-bottom {
631 | transform: translate(0px, 100px);
632 | }
633 | &.jconfirm-animation-opacity {
634 |
635 | }
636 | &.jconfirm-animation-zoom {
637 | transform: scale(1.2);
638 | }
639 | &.jconfirm-animation-scale {
640 | transform: scale(0.5);
641 | }
642 | &.jconfirm-animation-none {
643 | visibility: hidden;
644 | }
645 | }
646 | }
647 |
648 | .jconfirm.jconfirm-supervan {
649 | .jconfirm-bg {
650 | background-color: rgba(54, 70, 93, .95);
651 | }
652 |
653 | .jconfirm-box {
654 | background-color: transparent;
655 |
656 | &.jconfirm-type-blue {
657 | border: none;
658 | }
659 | &.jconfirm-type-green {
660 | border: none;
661 | }
662 | &.jconfirm-type-red {
663 | border: none;
664 | }
665 | &.jconfirm-type-orange {
666 | border: none;
667 | }
668 | &.jconfirm-type-purple {
669 | border: none;
670 | }
671 | &.jconfirm-type-dark {
672 | border: none;
673 | }
674 |
675 | div.jconfirm-closeIcon {
676 | color: white;
677 | }
678 |
679 | div.jconfirm-title-c {
680 | text-align: center;
681 | color: white;
682 | font-size: 28px;
683 | font-weight: normal;
684 | > * {
685 | padding-bottom: 25px;
686 | }
687 |
688 | .jconfirm-icon-c {
689 | margin-right: 8px;
690 | margin-left: 0px;
691 | }
692 | }
693 | div.jconfirm-content-pane {
694 | margin-bottom: 25px;
695 | }
696 | div.jconfirm-content {
697 | text-align: center;
698 | color: white;
699 |
700 | &:empty {
701 | &:before {
702 |
703 | }
704 | &:after {
705 |
706 | }
707 | }
708 | }
709 | .jconfirm-buttons {
710 | text-align: center;
711 |
712 | button {
713 | font-size: 16px;
714 | border-radius: 2px;
715 | background: darken(#36465D, 3%);
716 | text-shadow: none;
717 | border: none;
718 | color: white;
719 | padding: 10px;
720 | min-width: 100px;
721 | }
722 | button + button {
723 |
724 | }
725 | }
726 | &.hilight {
727 |
728 | }
729 | }
730 |
731 | &.jconfirm-rtl {
732 | .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
733 | margin-left: 8px;
734 | margin-right: 0px;
735 | }
736 | }
737 | }
738 |
739 | .jconfirm.jconfirm-material {
740 | .jconfirm-bg {
741 | background-color: rgba(0, 0, 0, .67);
742 | }
743 | .jconfirm-box {
744 | background-color: white;
745 | box-shadow: 0 7px 8px -4px rgba(0, 0, 0, .2), 0 13px 19px 2px rgba(0, 0, 0, .14), 0 5px 24px 4px rgba(0, 0, 0, .12);
746 | padding: 30px 25px 10px 25px;
747 |
748 | .jconfirm-title-c .jconfirm-icon-c {
749 | margin-right: 8px;
750 | margin-left: 0px;
751 | }
752 |
753 | div.jconfirm-closeIcon {
754 | color: rgba(0, 0, 0, .87);
755 | }
756 |
757 | div.jconfirm-title-c {
758 | color: rgba(0, 0, 0, .87);
759 | font-size: 22px;
760 | font-weight: bold;
761 | }
762 | div.jconfirm-content {
763 | color: rgba(0, 0, 0, .87);
764 |
765 | &:empty {
766 | &:before {
767 |
768 | }
769 | &:after {
770 |
771 | }
772 | }
773 | }
774 | .jconfirm-buttons {
775 | text-align: right;
776 |
777 | button {
778 | text-transform: uppercase;
779 | font-weight: 500;
780 | }
781 | button + button {
782 |
783 | }
784 | }
785 | &.hilight {
786 |
787 | }
788 | }
789 |
790 | &.jconfirm-rtl {
791 | .jconfirm-title-c .jconfirm-icon-c {
792 | margin-left: 8px;
793 | margin-right: 0px;
794 | }
795 | }
796 | }
797 |
798 | .jconfirm.jconfirm-bootstrap {
799 | .jconfirm-bg {
800 | background-color: rgba(0, 0, 0, .21);
801 | }
802 |
803 | .jconfirm-box {
804 | background-color: white;
805 | box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.2);
806 | border: solid 1px rgba(0, 0, 0, 0.4);
807 | padding: 15px 0 0;
808 |
809 | .jconfirm-title-c .jconfirm-icon-c {
810 | margin-right: 8px;
811 | margin-left: 0px;
812 | }
813 |
814 | div.jconfirm-closeIcon {
815 | color: rgba(0, 0, 0, 0.87);
816 | }
817 |
818 | div.jconfirm-title-c {
819 | color: rgba(0, 0, 0, 0.87);
820 | font-size: 22px;
821 | font-weight: bold;
822 | padding-left: 15px;
823 | padding-right: 15px;
824 | }
825 | div.jconfirm-content-pane {
826 |
827 | }
828 | div.jconfirm-content {
829 | color: rgba(0, 0, 0, 0.87);
830 | padding: 0px 15px;
831 |
832 | &:empty {
833 | &:before {
834 |
835 | }
836 | &:after {
837 |
838 | }
839 | }
840 | }
841 | .jconfirm-buttons {
842 | text-align: right;
843 | padding: 10px;
844 | margin: -5px 0 0px;
845 | border-top: solid 1px #ddd;
846 | overflow: hidden;
847 | border-radius: 0 0 4px 4px;
848 |
849 | button {
850 | font-weight: 500;
851 | }
852 | button + button {
853 |
854 | }
855 | }
856 | &.hilight {
857 |
858 | }
859 | }
860 |
861 | &.jconfirm-rtl {
862 | .jconfirm-title-c .jconfirm-icon-c {
863 | margin-left: 8px;
864 | margin-right: 0px;
865 | }
866 | }
867 | }
868 |
869 | .jconfirm.jconfirm-modern {
870 | .jconfirm-bg {
871 | background-color: slategray;
872 | opacity: .6;
873 | }
874 |
875 | .jconfirm-box {
876 | background-color: white;
877 | box-shadow: 0 7px 8px -4px rgba(0, 0, 0, .2), 0 13px 19px 2px rgba(0, 0, 0, .14), 0 5px 24px 4px rgba(0, 0, 0, .12);
878 | padding: 30px 30px 15px;
879 |
880 | div.jconfirm-closeIcon {
881 | color: rgba(0, 0, 0, 0.87);
882 | top: 15px;
883 | right: 15px;
884 | }
885 |
886 | div.jconfirm-title-c {
887 | color: rgba(0, 0, 0, .87);
888 | font-size: 24px;
889 | font-weight: bold;
890 | text-align: center;
891 | margin-bottom: 10px;
892 |
893 | .jconfirm-icon-c {
894 | transition: transform .5s;
895 | transform: scale(0);
896 | display: block;
897 | margin-right: 0px;
898 | margin-left: 0px;
899 | margin-bottom: 10px;
900 | font-size: 69px;
901 | color: #aaa;
902 | }
903 | }
904 |
905 | div.jconfirm-content {
906 | text-align: center;
907 | font-size: 15px;
908 | color: #777;
909 | margin-bottom: 25px;
910 |
911 | &:empty {
912 | &:before {
913 |
914 | }
915 | &:after {
916 |
917 | }
918 | }
919 | }
920 | .jconfirm-buttons {
921 | text-align: center;
922 |
923 | button {
924 | font-weight: bold;
925 | text-transform: uppercase;
926 | transition: background .1s;
927 | padding: 10px 20px;
928 |
929 | &.btn-success {
930 |
931 | }
932 | }
933 | button + button {
934 | margin-left: 4px;
935 | }
936 | }
937 | }
938 | &.jconfirm-open {
939 | .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
940 | transform: scale(1);
941 | }
942 | }
943 | }
--------------------------------------------------------------------------------
/addons/whmcspf/templates.admin.php:
--------------------------------------------------------------------------------
1 |
5 |
6 |
25 |
26 |
27 |
30 |
31 | Header;
32 | $Footer = <<
38 |
39 |
65 |
66 |
67 |
当前运行版本: v1.5
68 | Footer;
69 | $info_management = <<
71 |
72 |
73 | 请稍后 , 正在加载数据
74 |
75 |
76 |
77 |
78 |
81 |
82 |
83 |
84 | ID |
85 | 服务ID |
86 | 已用流量(Mb) |
87 | 剩余流量(Mb) |
88 | 总流量(Mb) |
89 | 状态 |
90 | 解禁时间 |
91 | 更新时间 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
113 |
114 |
213 |
214 |
217 | info_managementtemp;
218 | $HelloWorld = null;
--------------------------------------------------------------------------------
/addons/whmcspf/whmcspf.php:
--------------------------------------------------------------------------------
1 | '端口转发流量统计',
10 | 'description' => '端口转发流量统计',
11 | 'author' => 'Flyqie',
12 | 'version' => '1.5',
13 | 'fields' => array(
14 | 'authkey' => array(
15 | 'FriendlyName' => '验证密钥',
16 | 'Type' => 'text',
17 | 'Size' => '500'
18 | )
19 | )
20 | );
21 | }
22 | function whmcspf_activate()
23 | {
24 | try {
25 | if (!Capsule::schema()->hasTable('mod_whmcspf')) {
26 | Capsule::schema()->create('mod_whmcspf', function ($table) {
27 | $table->increments('id');
28 | $table->text('serviceid');
29 | $table->text('bandwidth');
30 | $table->text('updatetime');
31 | });
32 | }
33 | if (!Capsule::schema()->hasTable('mod_whmcspf_suspservice')) {
34 | Capsule::schema()->create('mod_whmcspf_suspservice', function ($table) {
35 | $table->increments('id');
36 | $table->text('serviceid');
37 | $table->datetime('untime');
38 | $table->datetime('addtime');
39 | });
40 | }
41 | } catch (Exception $e) {
42 | return [
43 | 'status' => 'error',
44 | 'description' => '不能创建表 : ' . $e->getMessage()
45 | ];
46 | }
47 | return array('status' => 'success','description' => '插件已经成功激活');
48 | }
49 | function whmcspf_deactivate()
50 | {
51 | Capsule::schema()->dropIfExists('mod_whmcspf');
52 | Capsule::schema()->dropIfExists('mod_whmcspf_suspservice');
53 |
54 | return [
55 | 'status' => 'success',
56 | 'description' => '模块卸载成功,你不爱老夏了'
57 | ];
58 | }
59 | function whmcspf_output($vars)
60 | {
61 | if($_REQUEST['action'] == 'get_info_list'){
62 | if(@$_REQUEST['ajax'] != 'true'){
63 | exit('禁止直接访问');
64 | }
65 | $infolist = Capsule::table('mod_whmcspf')->get();
66 | $infolistarray = array();
67 | $num = 0;
68 | foreach ($infolist as $values) {
69 | $suspfind = Capsule::table('mod_whmcspf_suspservice')->where('serviceid',$values->serviceid)->first();
70 | $PackAgeINfo = Capsule::table('tblproducts')->where('id',Capsule::table('tblhosting')->where('id',$values->serviceid)->first()->packageid)->first();
71 | if($PackAgeINfo){
72 | $AllBandwidth = $PackAgeINfo->configoption1;
73 | }else{
74 | $AllBandwidth = 0;
75 | }
76 | //$AllBandwidth = $PackAgeINfo->configoption1;
77 | $FreeBandwidth = $AllBandwidth - $values->bandwidth;
78 | if($FreeBandwidth < 0){
79 | $FreeBandwidth = '0';
80 | }
81 | if($suspfind){
82 | $Status = '流量超限';
83 | $unsptime = $suspfind->untime;
84 | }else{
85 | $Status = '正常';
86 | $unsptime = '无';
87 | }
88 | $infolistarray[$num]['id'] = $values->id;
89 | $infolistarray[$num]['serviceid'] = '#'.$values->serviceid.'';
90 | $infolistarray[$num]['usedbandwidth'] = $values->bandwidth;
91 | $infolistarray[$num]['freebandwidth'] = $FreeBandwidth;
92 | $infolistarray[$num]['allbandwidth'] = $AllBandwidth;
93 | $infolistarray[$num]['updatetime'] = date('Y-m-d H:i:s', $values->updatetime);
94 | $infolistarray[$num]['unsptime'] = $unsptime;
95 | $infolistarray[$num]['status'] = $Status;
96 | $num++;
97 | }
98 | $Infoarray['result'] = 'success';
99 | $Infoarray['info'] = $infolistarray;
100 | header('Content-Type: text/json; charset=utf-8');
101 | exit(json_encode($Infoarray));
102 | }else{
103 | include 'templates.admin.php';
104 | if(@$_REQUEST['ajax'] != 'true'){
105 | echo $Header.PHP_EOL.$info_management.PHP_EOL.$Footer.PHP_EOL;
106 | }else{
107 | exit($info_management.PHP_EOL);
108 | }
109 | }
110 | }
111 | function whmcspf_clientarea($vars)
112 | {
113 | if(@$_REQUEST['authkey'] != $vars['authkey']){
114 | exit('验证密钥错误');
115 | }else{
116 | $PackAgeINfo = Capsule::table('tblproducts')->where('id',Capsule::table('tblhosting')->where('id',$_REQUEST['serviceid'])->first()->packageid)->first();
117 | if(!$PackAgeINfo){
118 | exit('产品找不到');
119 | }
120 | if(!@$_REQUEST['serviceid'] || !@$_REQUEST['updatetime'] || !@$_REQUEST['bandwidth']){
121 | exit('参数不完整');
122 | }
123 | if(Capsule::table('tblhosting')->where('id',$_REQUEST['serviceid'])->first()->domainstatus != 'Active'){
124 | //说明已经被暂停了,可以直接不进行下面的操作
125 | exit('success');
126 | }
127 | if(Capsule::table('mod_whmcspf')->where('serviceid',$_REQUEST['serviceid'])->first()){
128 | Capsule::table('mod_whmcspf')->where('serviceid',$_REQUEST['serviceid'])->update(['updatetime' => $_REQUEST['updatetime'],'bandwidth' => $_REQUEST['bandwidth']]);
129 | }else{
130 | Capsule::table('mod_whmcspf')->insert(['serviceid' => $_REQUEST['serviceid'],'updatetime' => $_REQUEST['updatetime'],'serviceid' => $_REQUEST['serviceid'],'bandwidth' => $_REQUEST['bandwidth']]);
131 | }
132 | if(($PackAgeINfo->configoption1 < $_REQUEST['bandwidth'])){
133 | //流量超额
134 | $unsusptime = date("Y-m", strtotime("+1 months")).'-1';
135 | localAPI('ModuleSuspend', array('serviceid' => $_REQUEST['serviceid'],'suspendreason' => '流量超额'), Capsule::table('tbladmins')->first()->id);
136 | Capsule::table('tblhosting')->where('id',$_REQUEST['serviceid'])->update(['domainstatus' => 'Suspended']);
137 | whmcspf_setCustomfieldsValue('forwardstatus','maxtra',$_REQUEST['serviceid'],null);
138 | //如果产品到期时间小于解除暂停的时间,那么不作处理
139 | if(strtotime($unsusptime) < strtotime(Capsule::table('tblhosting')->where('id',$_REQUEST['serviceid'])->first()->nextduedate)){
140 | Capsule::table('mod_whmcspf_suspservice')->insert(['serviceid' => $_REQUEST['serviceid'],'untime' => $unsusptime,'addtime' => date("Y-m-d")]);
141 | }
142 | }
143 | whmcspf_setCustomfieldsValue('bandwidth',$_REQUEST['bandwidth'],$_REQUEST['serviceid'],null);
144 | exit('success');
145 | }
146 | }
147 |
148 | function whmcspf_setCustomfieldsValue($field,$value,$servid,$uid){
149 | $ownerRow = Capsule::table('tblhosting')->where('id',$servid)->first();
150 | if (!$ownerRow){
151 | return false;
152 | }
153 | if (!is_null($uid) && $uid != $ownerRow->userid){
154 | return false;
155 | }
156 | $res = Capsule::table('tblcustomfields')->where('relid',$ownerRow->packageid)->where('fieldname',$field)->first();
157 | if ($res) {
158 | $fieldValue = Capsule::table('tblcustomfieldsvalues')->where('relid',$ownerRow->id)->where('fieldid',$res->id)->first();
159 | if ($fieldValue) {
160 | if($fieldValue->value != $value) {
161 | Capsule::table('tblcustomfieldsvalues')->where('relid',$ownerRow->id)->where('fieldid', $res->id)->update(['value' => $value,]);
162 | }else{
163 | Capsule::table('tblcustomfieldsvalues')->insert(['relid' => $ownerRow->id,'fieldid' => $res->id,'value' => $value]);
164 | }
165 | }else{
166 | Capsule::table('tblcustomfieldsvalues')->insert(['relid' => $ownerRow->id,'fieldid' => $res->id,'value' => $value]);
167 | }
168 | }
169 | }
--------------------------------------------------------------------------------
/pfnode/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "workerman/workerman": "^3.5",
4 | "topthink/think-orm": "^1.2",
5 | "predis/predis": "^1.1"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/pfnode/config.php:
--------------------------------------------------------------------------------
1 |
3 | //验证用户名
4 | $authusername = 'admin';
5 | //验证密码
6 | $authpassword = 'admin';
7 | //端口最大
8 | $portmax = 4095;
9 | //端口最小
10 | $portmin = 1000;
11 | //端口单次最大生成次数
12 | $portmakemax = 30;
13 | //当前服务器IP
14 | $serverip = '127.0.0.1';
15 | //网站地址
16 | $websiteurl = 'http://www.baidu.com';
17 | //与网站上的插件验证密钥一致
18 | $WebsiteAuthkey = '';
19 | //Redis IP
20 | $RedisIP = '';
21 | //Redis Port
22 | $RedisPort = 6379;
23 | //Redis Auth Pass
24 | $RedisPass = '';
25 | //<------- 信息填写结束! ------>
--------------------------------------------------------------------------------
/pfnode/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TachibanaSuzume/WhmcsPortForward/ebdbb8119bd8d3604636a5b99a57c6ff20c27f4d/pfnode/database.db
--------------------------------------------------------------------------------
/pfnode/forward_service/ForwardSystem:
--------------------------------------------------------------------------------
1 | Hello,world!
--------------------------------------------------------------------------------
/pfnode/service_file_template.php:
--------------------------------------------------------------------------------
1 | 'tcp','host' => $RedisIP,'port' => $RedisPort,'parameters'=>['password' => $RedisPass]]);
8 | if('[PTYPE]' == 'udp'){
9 | $GlobalProxyService[[SERID]]['raddress'] = 'udp://[RSIP]:[RPORT]';
10 | }else{
11 | $GlobalProxyService[[SERID]]['raddress'] = 'tcp://[RSIP]:[RPORT]';
12 | }
13 | if('[PTYPE]' == 'udp'){
14 | $GlobalProxyService[[SERID]]['worker'] = new Worker('udp://0.0.0.0:[SPORT]');
15 | }else{
16 | $GlobalProxyService[[SERID]]['worker'] = new Worker('tcp://0.0.0.0:[SPORT]');
17 | }
18 | ($GlobalProxyService[[SERID]]['worker'])->name = 'Service [SERID] Forward Worker';
19 | if('[PTYPE]' == 'udp'){
20 | ($GlobalProxyService[[SERID]]['worker'])->onConnect = function($connection)use($GlobalProxyService){
21 | $connection_to_r = new AsyncUdpConnection($GlobalProxyService[[SERID]]['raddress']);
22 | $connection_to_r->onMessage = function($connection_to_r, $buffer)use($connection,$GlobalProxyService){
23 | ($GlobalProxyService[[SERID]]['client'])->set('[SERID]_download',(($GlobalProxyService[[SERID]]['client'])->get('[SERID]_download'))+strlen($buffer));
24 | $connection->send($buffer);
25 | };
26 | $connection_to_r->onClose = function($connection_to_r)use($connection){
27 | $connection->close();
28 | };
29 | $connection_to_r->connect();
30 | $connection->onMessage = function($connection, $buffer)use($connection_to_r,$GlobalProxyService){
31 | ($GlobalProxyService[[SERID]]['client'])->set('[SERID]_upload',(($GlobalProxyService[[SERID]]['client'])->get('[SERID]_upload'))+strlen($buffer));
32 | $connection_to_r->send($buffer);
33 | };
34 | $connection->onClose = function($connection)use($connection_to_r){
35 | $connection_to_r->close();
36 | };
37 | $connection->onError = function($connection)use($connection_to_r){
38 | @$connection_to_r->close();
39 | };
40 | };
41 | }else{
42 | ($GlobalProxyService[[SERID]]['worker'])->onConnect = function($connection)use($GlobalProxyService){
43 | $connection_to_r = new AsyncTcpConnection($GlobalProxyService[[SERID]]['raddress']);
44 | $connection_to_r->onMessage = function($connection_to_r, $buffer)use($connection,$GlobalProxyService){
45 | ($GlobalProxyService[[SERID]]['client'])->set('[SERID]_download',(($GlobalProxyService[[SERID]]['client'])->get('[SERID]_download'))+strlen($buffer));
46 | $connection->send($buffer);
47 | };
48 | $connection_to_r->onClose = function($connection_to_r)use($connection){
49 | $connection->close();
50 | };
51 | $connection_to_r->onError = function($connection_to_r)use($connection){
52 | $connection->close();
53 | };
54 | $connection_to_r->connect();
55 | $connection->onMessage = function($connection, $buffer)use($connection_to_r,$GlobalProxyService){
56 | ($GlobalProxyService[[SERID]]['client'])->set('[SERID]_upload',(($GlobalProxyService[[SERID]]['client'])->get('[SERID]_upload'))+strlen($buffer));
57 | $connection_to_r->send($buffer);
58 | };
59 | $connection_to_r->onBufferFull = function($connection_to_r)use($connection){
60 | $connection->pauseRecv();
61 | };
62 | $connection->onBufferFull = function($connection)use($connection_to_r){
63 | $connection_to_r->pauseRecv();
64 | };
65 | $connection->onBufferDrain = function($connection)use($connection_to_r){
66 | $connection_to_r->resumeRecv();
67 | };
68 | $connection_to_r->onBufferDrain = function($connection_to_r)use($connection){
69 | $connection->resumeRecv();
70 | };
71 | $connection->onClose = function($connection)use($connection_to_r){
72 | $connection_to_r->close();
73 | };
74 | $connection->onError = function($connection)use($connection_to_r){
75 | $connection_to_r->close();
76 | };
77 | };
78 | }
79 | /**
80 | if(!defined('GLOBAL_START')){
81 | Worker::runAll();
82 | }
83 | **/
84 | ($GlobalProxyService[[SERID]]['worker'])->listen();
85 | /**
86 | $GlobalProxyService[[SERID]]['workerstop'] = false;
87 | ($GlobalProxyService[[SERID]]['worker'])->listen();
88 | $Service_[SERID]_Timer = Timer::add(1, function()use(&$Service_[SERID]_Timer){
89 | global $GlobalProxyService;
90 | $StopService = $GlobalProxyService[[SERID]]['workerstop'];
91 | if($StopService){
92 | ($GlobalProxyService[[SERID]]['worker'])->stop();
93 | echo 'Worker[SERID]STOP!!'.PHP_EOL;
94 | unset($GlobalProxyService[[SERID]]);
95 | Timer::del($Service_[SERID]_Timer);
96 | }
97 | });
98 | **/
--------------------------------------------------------------------------------
/pfnode/start.php:
--------------------------------------------------------------------------------
1 | name = 'Forword Serice Autoloader';
8 | $autoload_worker->reloadable = false;
9 | $autoload_tmp_file_info_main = json_decode(@file_get_contents(__DIR__.'/autoload.tmp'),true);
10 | if(!$autoload_tmp_file_info_main){
11 | $autoload_last_mtime = time();
12 | }else{
13 | $autoload_last_mtime = $autoload_tmp_file_info_main['lastmtime'];
14 | }
15 | $autoload_last_file_list = array();
16 | $autoload_worker->onWorkerStart = function(){
17 | global $autoload_monitor_dir;
18 | Timer::add(10, 'autoload_check_files_change', array($autoload_monitor_dir));
19 | };
20 | if(!function_exists('autoload_check_files_change')){
21 | function autoload_check_files_change($monitor_dir){
22 | global $autoload_last_mtime,$autoload_last_file_list;
23 | $autoload_tmp_file_info = json_decode(@file_get_contents(__DIR__.'/autoload.tmp'),true);
24 | $dir_iterator = new RecursiveDirectoryIterator($monitor_dir);
25 | $iterator = new RecursiveIteratorIterator($dir_iterator);
26 | $tmplist = array();
27 | foreach($iterator as $ListOne){
28 | $tmplist[] = (string)$ListOne;
29 | }
30 | if(!@$autoload_tmp_file_info['list']){
31 | $autoload_last_file_list = $tmplist;
32 | }else{
33 | $autoload_last_file_list = $autoload_tmp_file_info['list'];
34 | }
35 | $NeedReloadFile = array();
36 | foreach ($iterator as $file){
37 | $Keys = array_keys($autoload_last_file_list,(string)$file);
38 | if(pathinfo($file, PATHINFO_EXTENSION) != 'php'){
39 | unset($autoload_last_file_list[($Keys[0])]);
40 | continue;
41 | }
42 | if(empty(@$Keys[0]) && @$Keys[0] != 0){
43 | echo $file." update and reload#1\n";
44 | $NeedReloadFile[] = (string)$file;
45 | continue;
46 | }
47 | if($autoload_last_mtime < $file->getMTime()){
48 | echo $file." update and reload#2\n";
49 | $NeedReloadFile[] = (string)$file;
50 | continue;
51 | }
52 | unset($autoload_last_file_list[($Keys[0])]);
53 | }
54 | if(!empty($autoload_last_file_list)){
55 | foreach($autoload_last_file_list as $_autoload_last_file_list){
56 | if(!array_keys($NeedReloadFile,$_autoload_last_file_list)){
57 | $NeedReloadFile[] = $_autoload_last_file_list;
58 | }
59 | }
60 | }
61 | if(count($NeedReloadFile) > 0){
62 | echo "All update and reload\n";
63 | $autoload_last_mtime = time();
64 | file_put_contents(__DIR__.'/autoload.tmp',json_encode(array('list' => $tmplist,'lastmtime' => $autoload_last_mtime)));
65 | file_put_contents(__DIR__.'/autoreload.tmp',json_encode(array('reloadfile' => $NeedReloadFile)));
66 | posix_kill(posix_getppid(), SIGUSR1);
67 | sleep(2);
68 | return ;
69 | }else{
70 | $autoload_last_mtime = time();
71 | $autoload_last_file_list = $tmplist;
72 | }
73 | file_put_contents(__DIR__.'/autoload.tmp',json_encode(array('list' => $autoload_last_file_list,'lastmtime' => $autoload_last_mtime)));
74 | if(!file_exists(__DIR__.'/autoreload.tmp')){
75 | file_put_contents(__DIR__.'/autoreload.tmp',json_encode(array('reloadfile' => array())));
76 | }
77 | clearstatcache();
78 | }
79 | }
--------------------------------------------------------------------------------
/pfnode/start_http.php:
--------------------------------------------------------------------------------
1 | name = 'Http Api Server';
7 | $http_worker->count = 4;
8 | include __DIR__.'/config.php';
9 | $api_redis_client = new Predis\Client(['scheme' => 'tcp','host' => $RedisIP,'port' => $RedisPort,'parameters'=>['password' => $RedisPass]]);
10 | Db::setConfig(['type'=> 'sqlite','database'=> 'database.db','prefix'=> '','debug'=> true]);
11 | $http_worker->onMessage = function($connection, $data){
12 | global $api_redis_client;
13 | include __DIR__.'/config.php';
14 | if(!@$_REQUEST['username'] || !@$_REQUEST['password'] || !@$_REQUEST['action'] || !@$_REQUEST['serviceid']){
15 | $connection->send(json_encode(array('code' => 403,'msg' => '参数不全#1')));
16 | return ;
17 | }
18 | if((trim($_REQUEST['username']) != $authusername) || (trim($_REQUEST['password']) != $authpassword)){
19 | $connection->send(json_encode(array('code' => 403,'msg' => '鉴权错误')));
20 | return ;
21 | }
22 | if(trim($_REQUEST['action']) == 'add'){
23 | if(!@$_REQUEST['ptype'] || !@$_REQUEST['rport'] || !@$_REQUEST['rsip']){
24 | $connection->send(json_encode(array('code' => 500,'msg' => '参数不全#2')));
25 | return ;
26 | }
27 | if(Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->find()){
28 | $connection->send(json_encode(array('code' => 500,'msg' => 'ServiceID已经存在')));
29 | return ;
30 | }
31 | if(trim($_REQUEST['ptype']) != 'tcp' && trim($_REQUEST['ptype']) != 'udp'){
32 | $connection->send(json_encode(array('code' => 500,'msg' => '转发类别错误')));
33 | return ;
34 | }
35 | while(true){
36 | $makenum = 0;
37 | $portnum = mt_rand($portmin,$portmax);
38 | if($makenum >= $portmakemax){
39 | $portnum = null;
40 | break;
41 | }
42 | if(!(Db::table('pfinfo')->where('sport',$portnum)->find())){
43 | break;
44 | }
45 | $makenum++;
46 | }
47 | if(!$portnum){
48 | $connection->send(json_encode(array('code' => 500,'msg' => '端口生成次数已经超过限制,请稍候重试')));
49 | return ;
50 | }
51 | $ServiceFileInfo = pf_gen_service_php(trim($_REQUEST['ptype']),trim($_REQUEST['serviceid']),trim($_REQUEST['rsip']),trim($_REQUEST['rport']),$portnum);
52 | file_put_contents(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php',$ServiceFileInfo);
53 | $sqlreturn = Db::table('pfinfo')->insert(["bandwidth" => '0',"status" => 'ok',"updatetime" => time(),"addtime" => time(),"serviceid" => trim($_REQUEST['serviceid']),"ptype" => trim($_REQUEST['ptype']),"rsip" => trim($_REQUEST['rsip']),"rport" => trim($_REQUEST['rport']),"sport" => $portnum]);
54 | if($sqlreturn){
55 | $api_redis_client->set(trim($_REQUEST['serviceid']).'_upload','0');
56 | $api_redis_client->set(trim($_REQUEST['serviceid']).'_download','0');
57 | $connection->send(json_encode(array('code' => 200,'msg' => '添加成功','sport' => $portnum)));
58 | }else{
59 | $connection->send(json_encode(array('code' => 500,'msg' => '数据库操作失败')));
60 | @unlink(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php');
61 | }
62 | return ;
63 | }elseif(trim($_REQUEST['action']) == 'del'){
64 | $DelInfo = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->find();
65 | if(!$DelInfo){
66 | $connection->send(json_encode(array('code' => 500,'msg' => 'ServiceID不存在')));
67 | return ;
68 | }
69 | @unlink(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php');
70 | $sqlreturn = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->delete();
71 | if($sqlreturn){
72 | $api_redis_client->del(trim($_REQUEST['serviceid']).'_upload');
73 | $api_redis_client->del(trim($_REQUEST['serviceid']).'_download');
74 | $connection->send(json_encode(array('code' => 200,'msg' => '删除成功')));
75 | }else{
76 | $connection->send(json_encode(array('code' => 500,'msg' => '数据库操作失败')));
77 | }
78 | return ;
79 | }elseif(trim($_REQUEST['action']) == 'update'){
80 | $ServiceInfo = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->find();
81 | if(!$ServiceInfo){
82 | $connection->send(json_encode(array('code' => 500,'msg' => 'ServiceID不存在')));
83 | return ;
84 | }
85 | if(!@$_REQUEST['ptype'] || !@$_REQUEST['rport'] || !@$_REQUEST['rsip']){
86 | $connection->send(json_encode(array('code' => 500,'msg' => '参数不全#2')));
87 | return ;
88 | }
89 | if(trim($_REQUEST['ptype']) != 'tcp' && trim($_REQUEST['ptype']) != 'udp'){
90 | $connection->send(json_encode(array('code' => 500,'msg' => '转发类别错误')));
91 | return ;
92 | }
93 | $ServiceFileInfo = pf_gen_service_php(trim($_REQUEST['ptype']),trim($ServiceInfo['serviceid']),trim($_REQUEST['rsip']),trim($_REQUEST['rport']),trim($ServiceInfo['sport']));
94 | file_put_contents(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php',$ServiceFileInfo);
95 | $sqlreturn = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->update(["rsip" => trim($_REQUEST['rsip']),"rport" => trim($_REQUEST['rport']),"ptype" => trim($_REQUEST['ptype'])]);
96 | if($sqlreturn){
97 | $connection->send(json_encode(array('code' => 200,'msg' => '更新成功')));
98 | }else{
99 | $connection->send(json_encode(array('code' => 500,'msg' => '数据库操作失败')));
100 | }
101 | return ;
102 | }elseif(trim($_REQUEST['action']) == 'unsusp'){
103 | $ServiceInfo = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->find();
104 | if(!$ServiceInfo){
105 | $connection->send(json_encode(array('code' => 500,'msg' => 'ServiceID不存在')));
106 | return ;
107 | }
108 | $ServiceFileInfo = pf_gen_service_php(trim($ServiceInfo['ptype']),trim($ServiceInfo['serviceid']),trim($ServiceInfo['rsip']),trim($ServiceInfo['rport']),trim($ServiceInfo['sport']));
109 | file_put_contents(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php',$ServiceFileInfo);
110 | $sqlreturn = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->update(["status" => 'ok']);
111 | if($sqlreturn){
112 | $connection->send(json_encode(array('code' => 200,'msg' => '解除暂停成功')));
113 | }else{
114 | $connection->send(json_encode(array('code' => 500,'msg' => '数据库操作失败')));
115 | }
116 | return ;
117 | }elseif(trim($_REQUEST['action']) == 'rebuild'){
118 | $ServiceInfo = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->find();
119 | if(!$ServiceInfo){
120 | $connection->send(json_encode(array('code' => 500,'msg' => 'ServiceID不存在')));
121 | return ;
122 | }
123 | $ServiceFileInfo = pf_gen_service_php(trim($ServiceInfo['ptype']),trim($ServiceInfo['serviceid']),trim($ServiceInfo['rsip']),trim($ServiceInfo['rport']),trim($ServiceInfo['sport']));
124 | file_put_contents(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php',$ServiceFileInfo);
125 | $connection->send(json_encode(array('code' => 200,'msg' => '重建成功')));
126 | return ;
127 | }elseif(trim($_REQUEST['action']) == 'susp'){
128 | $ServiceInfo = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->find();
129 | if(!$ServiceInfo){
130 | $connection->send(json_encode(array('code' => 500,'msg' => 'ServiceID不存在')));
131 | return ;
132 | }
133 | @unlink(__DIR__.'/forward_service/'.trim($_REQUEST['serviceid']).'.php');
134 | $sqlreturn = Db::table('pfinfo')->where('serviceid',trim($_REQUEST['serviceid']))->update(["status" => 'susp']);
135 | if($sqlreturn){
136 | $connection->send(json_encode(array('code' => 200,'msg' => '暂停成功')));
137 | }else{
138 | $connection->send(json_encode(array('code' => 500,'msg' => '数据库操作失败')));
139 | }
140 | return ;
141 | }elseif(trim($_REQUEST['action']) == 'test'){
142 | $connection->send(json_encode(array('code' => 200,'msg' => '对接成功')));
143 | return ;
144 | }else{
145 | $connection->send(json_encode(array('code' => 404,'msg' => '动作不存在')));
146 | return ;
147 | }
148 | };
149 | if(!function_exists('pf_gen_service_php')){
150 | function pf_gen_service_php($ptype,$serviceid,$rsip,$rport,$sport){
151 | if(filter_var(trim($rsip), FILTER_VALIDATE_IP,FILTER_FLAG_IPV6)){
152 | $rsip = '['.trim($rsip).']';
153 | }
154 | $info = file_get_contents(__DIR__.'/service_file_template.php');
155 | $info = str_replace("[PTYPE]",$ptype,$info);
156 | $info = str_replace("[SERID]",$serviceid,$info);
157 | $info = str_replace("[RSIP]",$rsip,$info);
158 | $info = str_replace("[RPORT]",$rport,$info);
159 | $info = str_replace("[SPORT]",$sport,$info);
160 | return $info;
161 | }
162 | }
163 | if(!defined('GLOBAL_START'))
164 | {
165 | Worker::runAll();
166 | }
--------------------------------------------------------------------------------
/pfnode/start_report.php:
--------------------------------------------------------------------------------
1 | 'tcp','host' => $RedisIP,'port' => $RedisPort,'parameters'=>['password' => $RedisPass]]);
23 | $report_worker = new Worker();
24 | $report_worker->count = 1;
25 | $report_worker->name = 'Report Service';
26 | $report_worker->onWorkerStart = function($report_worker)
27 | {
28 | Db::setConfig(['type'=> 'sqlite','database'=> 'database.db','prefix'=> '','debug'=> true]);
29 | //流量统计上报
30 | \Workerman\Lib\Timer::add(30, function(){
31 | include __DIR__.'/config.php';
32 | try {
33 | $data = Db::table('pfinfo')->where('status','ok')->select();
34 | } catch (Exception $e) {
35 | return ;
36 | }
37 | foreach ($data as $dataone){
38 | $returnstatus = report_curl_post_https($websiteurl.'/?m=whmcspf&action=reporttraffic',array('serviceid' => $dataone['serviceid'],'authkey' => $WebsiteAuthkey,'updatetime' => $dataone['updatetime'],'bandwidth' => $dataone['bandwidth']));
39 | if(trim($returnstatus) != 'success'){
40 | echo '['.date("Y-m-d h:i:sa").'] '.'上报'.json_encode(array('serviceid' => $dataone['serviceid'],'updatetime' => $dataone['updatetime'],'bandwidth' => $dataone['bandwidth'])).'时失败,服务器返回'.$returnstatus.PHP_EOL;
41 | file_put_contents('error.log','['.date("Y-m-d h:i:sa").'] '.'上报'.json_encode(array('serviceid' => $dataone['serviceid'],'updatetime' => $dataone['updatetime'],'bandwidth' => $dataone['bandwidth'])).'时失败,服务器返回'.$returnstatus.PHP_EOL,FILE_APPEND);
42 | }
43 | }
44 | unset($data);
45 | });
46 | //流量实时统计
47 | \Workerman\Lib\Timer::add(17, function(){
48 | global $report_redis_client;
49 | include __DIR__.'/config.php';
50 | try {
51 | $data = Db::table('pfinfo')->where('status','ok')->select();
52 | } catch (Exception $e) {
53 | return ;
54 | }
55 | foreach ($data as $dataone){
56 | $UploadByte = @$report_redis_client->get($dataone['serviceid'].'_upload');
57 | @$report_redis_client->set($dataone['serviceid'].'_upload','0');
58 | if(!$UploadByte){
59 | $UploadByte = 0;
60 | }
61 | $UploadMb = round($UploadByte/1024/1024, 2);
62 | $DownloadByte = @$report_redis_client->get($dataone['serviceid'].'_download');
63 | @$report_redis_client->set($dataone['serviceid'].'_download','0');
64 | if(!$DownloadByte){
65 | $DownloadByte = 0;
66 | }
67 | $DownloadMb = round($DownloadByte/1024/1024, 2);
68 | $NewBandWidth = $UploadMb + $DownloadMb;
69 | //入库
70 | try {
71 | Db::table('pfinfo')->where('id',$dataone['id'])->update(["bandwidth" => $dataone['bandwidth'] + $NewBandWidth,"updatetime" => time()]);
72 | } catch (Exception $e) {
73 | }
74 | }
75 | unset($data);
76 | });
77 | };
78 | if(!defined('GLOBAL_START'))
79 | {
80 | Worker::runAll();
81 | }
--------------------------------------------------------------------------------
/pfnode/start_service.php:
--------------------------------------------------------------------------------
1 | name = 'Forword Serice Main';
6 | $service_worker->reloadable = false;
7 | if(!@$GlobalProxyService){
8 | $GlobalProxyService = array();
9 | }
10 | $service_worker->onWorkerStart = function(){
11 | global $GlobalProxyService;
12 | foreach(glob(__DIR__.'/forward_service/*.php') as $start_filet){
13 | require $start_filet;
14 | }
15 | };
16 | $service_worker->onWorkerReload = function($worker){
17 | global $GlobalProxyService;
18 | $autoreload_tmp_file_info_main = json_decode(@file_get_contents(__DIR__.'/autoreload.tmp'),true);
19 | if(@$autoreload_tmp_file_info_main['reloadfile']){
20 | $reloadfile = $autoreload_tmp_file_info_main['reloadfile'];
21 | foreach($reloadfile as $_reloadfile){
22 | $_reloadfile_name = pathinfo($_reloadfile, PATHINFO_BASENAME);
23 | $_reloadfile_name = @(explode('.',$_reloadfile_name))[0];
24 | if(@$GlobalProxyService[$_reloadfile_name]){
25 | echo $_reloadfile_name.'STOP!!!'.PHP_EOL;
26 | ($GlobalProxyService[$_reloadfile_name]['worker'])->stop();
27 | unset($GlobalProxyService[$_reloadfile_name]);
28 | }
29 | if(file_exists($_reloadfile)){
30 | require $_reloadfile;
31 | echo $_reloadfile.'START!!!'.PHP_EOL;
32 | }
33 | }
34 | }
35 | @unlink(__DIR__.'/autoreload.tmp');
36 | };
--------------------------------------------------------------------------------
/servers/portforward/portforward.php:
--------------------------------------------------------------------------------
1 | 'PortForward',
12 | 'APIVersion' => '1.1',
13 | 'RequiresServer' => true,
14 | );
15 | }
16 |
17 | function portforward_ConfigOptions()
18 | {
19 | return array(
20 | '每月流量(Mb)' => array(
21 | 'Type' => 'text',
22 | 'Size' => '500'
23 | )
24 | );
25 | }
26 |
27 | function portforward_CreateAccount(array $params)
28 | {
29 | try {
30 | $postfields['username'] = $params['serverusername'];
31 | $postfields['password'] = $params['serverpassword'];
32 | $postfields['action'] = 'add';
33 | $postfields['serviceid'] = $params['serviceid'];
34 | if(!filter_var(trim($params['customfields']['rsip']), FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) && !filter_var(trim($params['customfields']['rsip']), FILTER_VALIDATE_IP)){
35 | throw new Exception('IP不正确');
36 | }
37 | if(!is_numeric(trim($params['customfields']['rport'])) || trim($params['customfields']['rport']) > 25535 || trim($params['customfields']['rport']) < 1){
38 | throw new Exception('端口不正确');
39 | }
40 | $postfields['ptype'] = trim($params['customfields']['ptype']);
41 | $postfields['rport'] = trim($params['customfields']['rport']);
42 | $postfields['rsip'] = trim($params['customfields']['rsip']);
43 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
44 | if(!$ReturnInfo){
45 | throw new Exception('服务器返回信息为空');
46 | }
47 | if($ReturnInfo['code'] == 200){
48 | Capsule::table('tblhosting')->where('id',$params['serviceid'])->update(['domain' => $params['customfields']['rsip'].':'.trim($params['customfields']['rport'])]);
49 | portforward_setCustomfieldsValue('sport',$ReturnInfo['sport'],$params['serviceid'],null);
50 | return 'success';
51 | }else{
52 | throw new Exception('开通失败,'.$ReturnInfo['msg']);
53 | }
54 | } catch (Exception $e) {
55 | logModuleCall(
56 | 'portforward',
57 | __FUNCTION__,
58 | $params,
59 | $e->getMessage(),
60 | $e->getTraceAsString()
61 | );
62 | return $e->getMessage();
63 | }
64 | }
65 |
66 | function portforward_SuspendAccount(array $params)
67 | {
68 | try {
69 | $postfields['username'] = $params['serverusername'];
70 | $postfields['password'] = $params['serverpassword'];
71 | $postfields['action'] = 'susp';
72 | $postfields['serviceid'] = $params['serviceid'];
73 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
74 | if(!$ReturnInfo){
75 | throw new Exception('服务器返回信息为空');
76 | }
77 | if($ReturnInfo['code'] == 200){
78 | return 'success';
79 | }else{
80 | throw new Exception('暂停失败,'.$ReturnInfo['msg']);
81 | }
82 | } catch (Exception $e) {
83 | logModuleCall(
84 | 'portforward',
85 | __FUNCTION__,
86 | $params,
87 | $e->getMessage(),
88 | $e->getTraceAsString()
89 | );
90 | return $e->getMessage();
91 | }
92 | }
93 |
94 | function portforward_RebuildConf(array $params)
95 | {
96 | try {
97 | $postfields['username'] = $params['serverusername'];
98 | $postfields['password'] = $params['serverpassword'];
99 | $postfields['action'] = 'rebuild';
100 | $postfields['serviceid'] = $params['serviceid'];
101 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
102 | if(!$ReturnInfo){
103 | throw new Exception('服务器返回信息为空');
104 | }
105 | if($ReturnInfo['code'] == 200){
106 | return 'success';
107 | }else{
108 | throw new Exception('重建失败,'.$ReturnInfo['msg']);
109 | }
110 | } catch (Exception $e) {
111 | logModuleCall(
112 | 'portforward',
113 | __FUNCTION__,
114 | $params,
115 | $e->getMessage(),
116 | $e->getTraceAsString()
117 | );
118 | return $e->getMessage();
119 | }
120 | }
121 |
122 | function portforward_AdminCustomButtonArray(){
123 | return array(
124 | "重建" => "RebuildConf"
125 | );
126 | }
127 |
128 | function portforward_UnsuspendAccount(array $params)
129 | {
130 | try {
131 | $postfields['username'] = $params['serverusername'];
132 | $postfields['password'] = $params['serverpassword'];
133 | $postfields['action'] = 'unsusp';
134 | $postfields['serviceid'] = $params['serviceid'];
135 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
136 | if(!$ReturnInfo){
137 | throw new Exception('服务器返回信息为空');
138 | }
139 | if($ReturnInfo['code'] == 200){
140 | return 'success';
141 | }else{
142 | throw new Exception('解除暂停失败,'.$ReturnInfo['msg']);
143 | }
144 | } catch (Exception $e) {
145 | logModuleCall(
146 | 'portforward',
147 | __FUNCTION__,
148 | $params,
149 | $e->getMessage(),
150 | $e->getTraceAsString()
151 | );
152 | return $e->getMessage();
153 | }
154 | }
155 |
156 | function portforward_TerminateAccount(array $params)
157 | {
158 | try {
159 | $postfields['username'] = $params['serverusername'];
160 | $postfields['password'] = $params['serverpassword'];
161 | $postfields['action'] = 'del';
162 | $postfields['serviceid'] = $params['serviceid'];
163 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
164 | if(!$ReturnInfo){
165 | throw new Exception('服务器返回信息为空');
166 | }
167 | if($ReturnInfo['code'] == 200){
168 | return 'success';
169 | }else{
170 | throw new Exception('删除失败,'.$ReturnInfo['msg']);
171 | }
172 | } catch (Exception $e) {
173 | logModuleCall(
174 | 'portforward',
175 | __FUNCTION__,
176 | $params,
177 | $e->getMessage(),
178 | $e->getTraceAsString()
179 | );
180 |
181 | return $e->getMessage();
182 | }
183 | }
184 |
185 | function portforward_ClientArea(array $params)
186 | {
187 | if($_REQUEST['pfaction'] == 'changevalue'){
188 | if(!$_REQUEST['rsip'] || !$_REQUEST['rport']){
189 | exit(json_encode(array('result' => 'failed','msg' => '转发到的IP和端口不得为空')));
190 | }
191 | if(!filter_var(trim($_REQUEST['rsip']), FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) && !filter_var(trim($_REQUEST['rsip']), FILTER_VALIDATE_IP)){
192 | exit(json_encode(array('result' => 'failed','msg' => 'IP不正确')));
193 | }
194 | if(!is_numeric(trim($_REQUEST['rport'])) || trim($_REQUEST['rport']) > 25535 || trim($_REQUEST['rport']) < 1){
195 | exit(json_encode(array('result' => 'failed','msg' => '端口不正确')));
196 | }
197 | $postfields['username'] = $params['serverusername'];
198 | $postfields['password'] = $params['serverpassword'];
199 | $postfields['action'] = 'update';
200 | $postfields['serviceid'] = $params['serviceid'];
201 | $postfields['rsip'] = trim($_REQUEST['rsip']);
202 | $postfields['rport'] = trim($_REQUEST['rport']);
203 | $postfields['ptype'] = trim($params['customfields']['ptype']);
204 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
205 | if(!$ReturnInfo){
206 | exit(json_encode(array('result' => 'failed','msg' => 'ServiceID不存在')));
207 | }
208 | if($ReturnInfo['code'] == 200){
209 | portforward_setCustomfieldsValue('rsip|源服务器IP',trim($_REQUEST['rsip']),$params['serviceid'],null);
210 | portforward_setCustomfieldsValue('rport|源服务器端口',trim($_REQUEST['rport']),$params['serviceid'],null);
211 | Capsule::table('tblhosting')->where('id',$params['serviceid'])->update(['domain' => trim($_REQUEST['rsip']).':'.trim($_REQUEST['rport'])]);
212 | exit(json_encode(array('result' => 'success','msg' => '')));
213 | }else{
214 | exit(json_encode(array('result' => 'failed','msg' => $ReturnInfo['msg'])));
215 | }
216 | }
217 | if(trim($params['customfields']['forwardstatus']) == 'maxtra'){
218 | $templatevar['forwardstatus'] = '流量超额';
219 | }else{
220 | $templatevar['forwardstatus'] = '正常';
221 | }
222 | $ProxyIP = null;
223 | $HashInfo = portforward_gethashinfo($params['serveraccesshash']);
224 | if(@$HashInfo['proxyip']){
225 | $ProxyIPArray = explode(',',trim($HashInfo['proxyip']));
226 | foreach($ProxyIPArray as $ProxyIPOne){
227 | $ProxyIP .= $ProxyIPOne.'
';
228 | }
229 | $ProxyIP = rtrim($ProxyIP,'
');
230 | }else{
231 | $ProxyIP .= $params['serverip'];
232 | }
233 | $ProxyIP = base64_encode($ProxyIP);
234 | $templatevar['ptype'] = trim($params['customfields']['ptype']);
235 | $templatevar['sport'] = trim($params['customfields']['sport']);
236 | $templatevar['sip'] = $ProxyIP;
237 | $templatevar['rsip'] = trim($params['customfields']['rsip']);
238 | $templatevar['rport'] = trim($params['customfields']['rport']);
239 | $templatevar['usedbandwidth'] = trim($params['customfields']['bandwidth']);
240 | $templatevar['alldbandwidth'] = trim($params['configoption1']);
241 | $templatevar['freedbandwidth'] = $templatevar['alldbandwidth'] - $templatevar['usedbandwidth'];
242 | if((int)$templatevar['freedbandwidth'] < 0){
243 | $templatevar['freedbandwidth'] = '0';
244 | }
245 | return array(
246 | 'tabOverviewReplacementTemplate' => 'templates/clientarea.tpl',
247 | 'templateVariables' => $templatevar,
248 | );
249 | }
250 |
251 | function portforward_curlconnect($url,$postfields){
252 | $ch = curl_init();
253 | curl_setopt($ch, CURLOPT_URL, $url);
254 | curl_setopt($ch, CURLOPT_POST, 1);
255 | curl_setopt($ch, CURLOPT_TIMEOUT, 20);
256 | curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
257 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
258 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
259 | curl_setopt($ch, CURLOPT_HEADER, 0);
260 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
261 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
262 | $data = curl_exec($ch);
263 | curl_close($ch);
264 | return $data;
265 | }
266 |
267 | function portforward_TestConnection($params){
268 | $postfields['username'] = $params['serverusername'];
269 | $postfields['password'] = $params['serverpassword'];
270 | $postfields['action'] = 'test';
271 | $postfields['serviceid'] = 'none';
272 | $ReturnInfo = json_decode(portforward_curlconnect('http://'.$params['serverip'].':1388/',$postfields),true);
273 | if(!$ReturnInfo){
274 | return array('success' => false,'error' => '服务器返回信息为空');
275 | }
276 | if($ReturnInfo['code'] == 200){
277 | return array('success' => true,'error' => '');
278 | }else{
279 | return array('success' => false,'error' => $ReturnInfo['msg']);
280 | }
281 | }
282 |
283 | function portforward_setCustomfieldsValue($field,$value,$servid,$uid){
284 | $ownerRow = Capsule::table('tblhosting')->where('id',$servid)->first();
285 | if (!$ownerRow){
286 | return false;
287 | }
288 | if (!is_null($uid) && $uid != $ownerRow->userid){
289 | return false;
290 | }
291 | $res = Capsule::table('tblcustomfields')->where('relid',$ownerRow->packageid)->where('fieldname',$field)->first();
292 | if ($res) {
293 | $fieldValue = Capsule::table('tblcustomfieldsvalues')->where('relid',$ownerRow->id)->where('fieldid',$res->id)->first();
294 | if ($fieldValue) {
295 | if($fieldValue->value != $value) {
296 | Capsule::table('tblcustomfieldsvalues')->where('relid',$ownerRow->id)->where('fieldid', $res->id)->update(['value' => $value,]);
297 | }else{
298 | Capsule::table('tblcustomfieldsvalues')->insert(['relid' => $ownerRow->id,'fieldid' => $res->id,'value' => $value]);
299 | }
300 | }else{
301 | Capsule::table('tblcustomfieldsvalues')->insert(['relid' => $ownerRow->id,'fieldid' => $res->id,'value' => $value]);
302 | }
303 | }
304 | }
305 |
306 | function portforward_gethashinfo($data){
307 | preg_match_all( '/<(.*?)>([^<]+)<\/\\1>/i', $data, $matches );
308 | $result = array();
309 | foreach($matches[1] as $k => $v){
310 | $result[$v] = $matches[2][$k];
311 | }
312 | return $result;
313 | }
--------------------------------------------------------------------------------
/servers/portforward/templates/clientarea.tpl:
--------------------------------------------------------------------------------
1 | {if $rawstatus eq 'active'}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
服务信息 Service Detail
10 |
11 |
12 |
52 |
53 |
54 |
57 |
58 |
59 |
产品信息 Product Detail
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 转发类型
68 |
69 |
70 | {$ptype}
71 |
72 |
73 |
74 |
75 |
76 |
77 | 转发IP
78 |
79 |
80 | 点我获取IP
81 |
82 |
83 |
84 |
85 |
86 |
87 | 转发端口
88 |
89 |
90 | {$sport}
91 |
92 |
93 |
94 |
95 |
96 |
97 | 源IP
98 |
99 |
100 | {$rsip}
101 |
102 |
103 |
104 |
105 |
106 |
107 | 源端口
108 |
109 |
110 | {$rport}
111 |
112 |
113 |
114 |
115 |
116 |
117 | 转发状态
118 |
119 |
120 | {$forwardstatus}
121 |
122 |
123 |
124 |
125 |
126 |
127 | 已用流量
128 |
129 |
130 | {$usedbandwidth} Mb
131 |
132 |
133 |
134 |
135 |
136 |
137 | 可用流量
138 |
139 |
140 | {$freedbandwidth} Mb
141 |
142 |
143 |
144 |
145 |
146 |
147 | 总流量
148 |
149 |
150 | {$alldbandwidth} Mb
151 |
152 |
153 |
154 |
155 |
156 | {literal}
157 |
238 | {else}
239 | 抱歉,该产品目前无法管理({$status})
240 | {if $suspendreason}
241 | ,原因:{$suspendreason}
242 | {/if}
243 | {/if}
--------------------------------------------------------------------------------
/servers/portforward/theme/base64.js:
--------------------------------------------------------------------------------
1 | /*
2 | * base64.js
3 | *
4 | * Licensed under the BSD 3-Clause License.
5 | * http://opensource.org/licenses/BSD-3-Clause
6 | *
7 | * References:
8 | * http://en.wikipedia.org/wiki/Base64
9 | */
10 | ;(function (global, factory) {
11 | typeof exports === 'object' && typeof module !== 'undefined'
12 | ? module.exports = factory(global)
13 | : typeof define === 'function' && define.amd
14 | ? define(factory) : factory(global)
15 | }((
16 | typeof self !== 'undefined' ? self
17 | : typeof window !== 'undefined' ? window
18 | : typeof global !== 'undefined' ? global
19 | : this
20 | ), function(global) {
21 | 'use strict';
22 | // existing version for noConflict()
23 | global = global || {};
24 | var _Base64 = global.Base64;
25 | var version = "2.5.1";
26 | // if node.js and NOT React Native, we use Buffer
27 | var buffer;
28 | if (typeof module !== 'undefined' && module.exports) {
29 | try {
30 | buffer = eval("require('buffer').Buffer");
31 | } catch (err) {
32 | buffer = undefined;
33 | }
34 | }
35 | // constants
36 | var b64chars
37 | = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
38 | var b64tab = function(bin) {
39 | var t = {};
40 | for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
41 | return t;
42 | }(b64chars);
43 | var fromCharCode = String.fromCharCode;
44 | // encoder stuff
45 | var cb_utob = function(c) {
46 | if (c.length < 2) {
47 | var cc = c.charCodeAt(0);
48 | return cc < 0x80 ? c
49 | : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
50 | + fromCharCode(0x80 | (cc & 0x3f)))
51 | : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
52 | + fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
53 | + fromCharCode(0x80 | ( cc & 0x3f)));
54 | } else {
55 | var cc = 0x10000
56 | + (c.charCodeAt(0) - 0xD800) * 0x400
57 | + (c.charCodeAt(1) - 0xDC00);
58 | return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
59 | + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
60 | + fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
61 | + fromCharCode(0x80 | ( cc & 0x3f)));
62 | }
63 | };
64 | var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
65 | var utob = function(u) {
66 | return u.replace(re_utob, cb_utob);
67 | };
68 | var cb_encode = function(ccc) {
69 | var padlen = [0, 2, 1][ccc.length % 3],
70 | ord = ccc.charCodeAt(0) << 16
71 | | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
72 | | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
73 | chars = [
74 | b64chars.charAt( ord >>> 18),
75 | b64chars.charAt((ord >>> 12) & 63),
76 | padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
77 | padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
78 | ];
79 | return chars.join('');
80 | };
81 | var btoa = global.btoa ? function(b) {
82 | return global.btoa(b);
83 | } : function(b) {
84 | return b.replace(/[\s\S]{1,3}/g, cb_encode);
85 | };
86 | var _encode = buffer ?
87 | buffer.from && Uint8Array && buffer.from !== Uint8Array.from
88 | ? function (u) {
89 | return (u.constructor === buffer.constructor ? u : buffer.from(u))
90 | .toString('base64')
91 | }
92 | : function (u) {
93 | return (u.constructor === buffer.constructor ? u : new buffer(u))
94 | .toString('base64')
95 | }
96 | : function (u) { return btoa(utob(u)) }
97 | ;
98 | var encode = function(u, urisafe) {
99 | return !urisafe
100 | ? _encode(String(u))
101 | : _encode(String(u)).replace(/[+\/]/g, function(m0) {
102 | return m0 == '+' ? '-' : '_';
103 | }).replace(/=/g, '');
104 | };
105 | var encodeURI = function(u) { return encode(u, true) };
106 | // decoder stuff
107 | var re_btou = new RegExp([
108 | '[\xC0-\xDF][\x80-\xBF]',
109 | '[\xE0-\xEF][\x80-\xBF]{2}',
110 | '[\xF0-\xF7][\x80-\xBF]{3}'
111 | ].join('|'), 'g');
112 | var cb_btou = function(cccc) {
113 | switch(cccc.length) {
114 | case 4:
115 | var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
116 | | ((0x3f & cccc.charCodeAt(1)) << 12)
117 | | ((0x3f & cccc.charCodeAt(2)) << 6)
118 | | (0x3f & cccc.charCodeAt(3)),
119 | offset = cp - 0x10000;
120 | return (fromCharCode((offset >>> 10) + 0xD800)
121 | + fromCharCode((offset & 0x3FF) + 0xDC00));
122 | case 3:
123 | return fromCharCode(
124 | ((0x0f & cccc.charCodeAt(0)) << 12)
125 | | ((0x3f & cccc.charCodeAt(1)) << 6)
126 | | (0x3f & cccc.charCodeAt(2))
127 | );
128 | default:
129 | return fromCharCode(
130 | ((0x1f & cccc.charCodeAt(0)) << 6)
131 | | (0x3f & cccc.charCodeAt(1))
132 | );
133 | }
134 | };
135 | var btou = function(b) {
136 | return b.replace(re_btou, cb_btou);
137 | };
138 | var cb_decode = function(cccc) {
139 | var len = cccc.length,
140 | padlen = len % 4,
141 | n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
142 | | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
143 | | (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0)
144 | | (len > 3 ? b64tab[cccc.charAt(3)] : 0),
145 | chars = [
146 | fromCharCode( n >>> 16),
147 | fromCharCode((n >>> 8) & 0xff),
148 | fromCharCode( n & 0xff)
149 | ];
150 | chars.length -= [0, 0, 2, 1][padlen];
151 | return chars.join('');
152 | };
153 | var _atob = global.atob ? function(a) {
154 | return global.atob(a);
155 | } : function(a){
156 | return a.replace(/\S{1,4}/g, cb_decode);
157 | };
158 | var atob = function(a) {
159 | return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ''));
160 | };
161 | var _decode = buffer ?
162 | buffer.from && Uint8Array && buffer.from !== Uint8Array.from
163 | ? function(a) {
164 | return (a.constructor === buffer.constructor
165 | ? a : buffer.from(a, 'base64')).toString();
166 | }
167 | : function(a) {
168 | return (a.constructor === buffer.constructor
169 | ? a : new buffer(a, 'base64')).toString();
170 | }
171 | : function(a) { return btou(_atob(a)) };
172 | var decode = function(a){
173 | return _decode(
174 | String(a).replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
175 | .replace(/[^A-Za-z0-9\+\/]/g, '')
176 | );
177 | };
178 | var noConflict = function() {
179 | var Base64 = global.Base64;
180 | global.Base64 = _Base64;
181 | return Base64;
182 | };
183 | // export Base64
184 | global.Base64 = {
185 | VERSION: version,
186 | atob: atob,
187 | btoa: btoa,
188 | fromBase64: decode,
189 | toBase64: encode,
190 | utob: utob,
191 | encode: encode,
192 | encodeURI: encodeURI,
193 | btou: btou,
194 | decode: decode,
195 | noConflict: noConflict,
196 | __buffer__: buffer
197 | };
198 | // if ES5 is available, make Base64.extendString() available
199 | if (typeof Object.defineProperty === 'function') {
200 | var noEnum = function(v){
201 | return {value:v,enumerable:false,writable:true,configurable:true};
202 | };
203 | global.Base64.extendString = function () {
204 | Object.defineProperty(
205 | String.prototype, 'fromBase64', noEnum(function () {
206 | return decode(this)
207 | }));
208 | Object.defineProperty(
209 | String.prototype, 'toBase64', noEnum(function (urisafe) {
210 | return encode(this, urisafe)
211 | }));
212 | Object.defineProperty(
213 | String.prototype, 'toBase64URI', noEnum(function () {
214 | return encode(this, true)
215 | }));
216 | };
217 | }
218 | //
219 | // export Base64 to the namespace
220 | //
221 | if (global['Meteor']) { // Meteor.js
222 | Base64 = global.Base64;
223 | }
224 | // module.exports and AMD are mutually exclusive.
225 | // module.exports has precedence.
226 | if (typeof module !== 'undefined' && module.exports) {
227 | module.exports.Base64 = global.Base64;
228 | }
229 | else if (typeof define === 'function' && define.amd) {
230 | // AMD. Register as an anonymous module.
231 | define([], function(){ return global.Base64 });
232 | }
233 | // that's it!
234 | return {Base64: global.Base64}
235 | }));
236 |
--------------------------------------------------------------------------------
/servers/portforward/theme/flags.css:
--------------------------------------------------------------------------------
1 | .flag {
2 | width: 16px;
3 | height: 11px;
4 | background:url(flags.png) no-repeat
5 | }
6 |
7 | .flag.flag-ad {background-position: -16px 0}
8 | .flag.flag-ae {background-position: -32px 0}
9 | .flag.flag-af {background-position: -48px 0}
10 | .flag.flag-ag {background-position: -64px 0}
11 | .flag.flag-ai {background-position: -80px 0}
12 | .flag.flag-al {background-position: -96px 0}
13 | .flag.flag-am {background-position: -112px 0}
14 | .flag.flag-an {background-position: -128px 0}
15 | .flag.flag-ao {background-position: -144px 0}
16 | .flag.flag-ar {background-position: -160px 0}
17 | .flag.flag-as {background-position: -176px 0}
18 | .flag.flag-at {background-position: -192px 0}
19 | .flag.flag-au {background-position: -208px 0}
20 | .flag.flag-aw {background-position: -224px 0}
21 | .flag.flag-az {background-position: -240px 0}
22 | .flag.flag-ba {background-position: 0 -11px}
23 | .flag.flag-bb {background-position: -16px -11px}
24 | .flag.flag-bd {background-position: -32px -11px}
25 | .flag.flag-be {background-position: -48px -11px}
26 | .flag.flag-bf {background-position: -64px -11px}
27 | .flag.flag-bg {background-position: -80px -11px}
28 | .flag.flag-bh {background-position: -96px -11px}
29 | .flag.flag-bi {background-position: -112px -11px}
30 | .flag.flag-bj {background-position: -128px -11px}
31 | .flag.flag-bm {background-position: -144px -11px}
32 | .flag.flag-bn {background-position: -160px -11px}
33 | .flag.flag-bo {background-position: -176px -11px}
34 | .flag.flag-br {background-position: -192px -11px}
35 | .flag.flag-bs {background-position: -208px -11px}
36 | .flag.flag-bt {background-position: -224px -11px}
37 | .flag.flag-bv {background-position: -240px -11px}
38 | .flag.flag-bw {background-position: 0 -22px}
39 | .flag.flag-by {background-position: -16px -22px}
40 | .flag.flag-bz {background-position: -32px -22px}
41 | .flag.flag-ca {background-position: -48px -22px}
42 | .flag.flag-catalonia {background-position: -64px -22px}
43 | .flag.flag-cd {background-position: -80px -22px}
44 | .flag.flag-cf {background-position: -96px -22px}
45 | .flag.flag-cg {background-position: -112px -22px}
46 | .flag.flag-ch {background-position: -128px -22px}
47 | .flag.flag-ci {background-position: -144px -22px}
48 | .flag.flag-ck {background-position: -160px -22px}
49 | .flag.flag-cl {background-position: -176px -22px}
50 | .flag.flag-cm {background-position: -192px -22px}
51 | .flag.flag-cn {background-position: -208px -22px}
52 | .flag.flag-co {background-position: -224px -22px}
53 | .flag.flag-cr {background-position: -240px -22px}
54 | .flag.flag-cu {background-position: 0 -33px}
55 | .flag.flag-cv {background-position: -16px -33px}
56 | .flag.flag-cw {background-position: -32px -33px}
57 | .flag.flag-cy {background-position: -48px -33px}
58 | .flag.flag-cz {background-position: -64px -33px}
59 | .flag.flag-de {background-position: -80px -33px}
60 | .flag.flag-dj {background-position: -96px -33px}
61 | .flag.flag-dk {background-position: -112px -33px}
62 | .flag.flag-dm {background-position: -128px -33px}
63 | .flag.flag-do {background-position: -144px -33px}
64 | .flag.flag-dz {background-position: -160px -33px}
65 | .flag.flag-ec {background-position: -176px -33px}
66 | .flag.flag-ee {background-position: -192px -33px}
67 | .flag.flag-eg {background-position: -208px -33px}
68 | .flag.flag-eh {background-position: -224px -33px}
69 | .flag.flag-england {background-position: -240px -33px}
70 | .flag.flag-er {background-position: 0 -44px}
71 | .flag.flag-es {background-position: -16px -44px}
72 | .flag.flag-et {background-position: -32px -44px}
73 | .flag.flag-eu {background-position: -48px -44px}
74 | .flag.flag-fi {background-position: -64px -44px}
75 | .flag.flag-fj {background-position: -80px -44px}
76 | .flag.flag-fk {background-position: -96px -44px}
77 | .flag.flag-fm {background-position: -112px -44px}
78 | .flag.flag-fo {background-position: -128px -44px}
79 | .flag.flag-fr {background-position: -144px -44px}
80 | .flag.flag-ga {background-position: -160px -44px}
81 | .flag.flag-gb {background-position: -176px -44px}
82 | .flag.flag-gd {background-position: -192px -44px}
83 | .flag.flag-ge {background-position: -208px -44px}
84 | .flag.flag-gf {background-position: -224px -44px}
85 | .flag.flag-gg {background-position: -240px -44px}
86 | .flag.flag-gh {background-position: 0 -55px}
87 | .flag.flag-gi {background-position: -16px -55px}
88 | .flag.flag-gl {background-position: -32px -55px}
89 | .flag.flag-gm {background-position: -48px -55px}
90 | .flag.flag-gn {background-position: -64px -55px}
91 | .flag.flag-gp {background-position: -80px -55px}
92 | .flag.flag-gq {background-position: -96px -55px}
93 | .flag.flag-gr {background-position: -112px -55px}
94 | .flag.flag-gs {background-position: -128px -55px}
95 | .flag.flag-gt {background-position: -144px -55px}
96 | .flag.flag-gu {background-position: -160px -55px}
97 | .flag.flag-gw {background-position: -176px -55px}
98 | .flag.flag-gy {background-position: -192px -55px}
99 | .flag.flag-hk {background-position: -208px -55px}
100 | .flag.flag-hm {background-position: -224px -55px}
101 | .flag.flag-hn {background-position: -240px -55px}
102 | .flag.flag-hr {background-position: 0 -66px}
103 | .flag.flag-ht {background-position: -16px -66px}
104 | .flag.flag-hu {background-position: -32px -66px}
105 | .flag.flag-ic {background-position: -48px -66px}
106 | .flag.flag-id {background-position: -64px -66px}
107 | .flag.flag-ie {background-position: -80px -66px}
108 | .flag.flag-il {background-position: -96px -66px}
109 | .flag.flag-im {background-position: -112px -66px}
110 | .flag.flag-in {background-position: -128px -66px}
111 | .flag.flag-io {background-position: -144px -66px}
112 | .flag.flag-iq {background-position: -160px -66px}
113 | .flag.flag-ir {background-position: -176px -66px}
114 | .flag.flag-is {background-position: -192px -66px}
115 | .flag.flag-it {background-position: -208px -66px}
116 | .flag.flag-je {background-position: -224px -66px}
117 | .flag.flag-jm {background-position: -240px -66px}
118 | .flag.flag-jo {background-position: 0 -77px}
119 | .flag.flag-jp {background-position: -16px -77px}
120 | .flag.flag-ke {background-position: -32px -77px}
121 | .flag.flag-kg {background-position: -48px -77px}
122 | .flag.flag-kh {background-position: -64px -77px}
123 | .flag.flag-ki {background-position: -80px -77px}
124 | .flag.flag-km {background-position: -96px -77px}
125 | .flag.flag-kn {background-position: -112px -77px}
126 | .flag.flag-kp {background-position: -128px -77px}
127 | .flag.flag-kr {background-position: -144px -77px}
128 | .flag.flag-kurdistan {background-position: -160px -77px}
129 | .flag.flag-kw {background-position: -176px -77px}
130 | .flag.flag-ky {background-position: -192px -77px}
131 | .flag.flag-kz {background-position: -208px -77px}
132 | .flag.flag-la {background-position: -224px -77px}
133 | .flag.flag-lb {background-position: -240px -77px}
134 | .flag.flag-lc {background-position: 0 -88px}
135 | .flag.flag-li {background-position: -16px -88px}
136 | .flag.flag-lk {background-position: -32px -88px}
137 | .flag.flag-lr {background-position: -48px -88px}
138 | .flag.flag-ls {background-position: -64px -88px}
139 | .flag.flag-lt {background-position: -80px -88px}
140 | .flag.flag-lu {background-position: -96px -88px}
141 | .flag.flag-lv {background-position: -112px -88px}
142 | .flag.flag-ly {background-position: -128px -88px}
143 | .flag.flag-ma {background-position: -144px -88px}
144 | .flag.flag-mc {background-position: -160px -88px}
145 | .flag.flag-md {background-position: -176px -88px}
146 | .flag.flag-me {background-position: -192px -88px}
147 | .flag.flag-mg {background-position: -208px -88px}
148 | .flag.flag-mh {background-position: -224px -88px}
149 | .flag.flag-mk {background-position: -240px -88px}
150 | .flag.flag-ml {background-position: 0 -99px}
151 | .flag.flag-mm {background-position: -16px -99px}
152 | .flag.flag-mn {background-position: -32px -99px}
153 | .flag.flag-mo {background-position: -48px -99px}
154 | .flag.flag-mp {background-position: -64px -99px}
155 | .flag.flag-mq {background-position: -80px -99px}
156 | .flag.flag-mr {background-position: -96px -99px}
157 | .flag.flag-ms {background-position: -112px -99px}
158 | .flag.flag-mt {background-position: -128px -99px}
159 | .flag.flag-mu {background-position: -144px -99px}
160 | .flag.flag-mv {background-position: -160px -99px}
161 | .flag.flag-mw {background-position: -176px -99px}
162 | .flag.flag-mx {background-position: -192px -99px}
163 | .flag.flag-my {background-position: -208px -99px}
164 | .flag.flag-mz {background-position: -224px -99px}
165 | .flag.flag-na {background-position: -240px -99px}
166 | .flag.flag-nc {background-position: 0 -110px}
167 | .flag.flag-ne {background-position: -16px -110px}
168 | .flag.flag-nf {background-position: -32px -110px}
169 | .flag.flag-ng {background-position: -48px -110px}
170 | .flag.flag-ni {background-position: -64px -110px}
171 | .flag.flag-nl {background-position: -80px -110px}
172 | .flag.flag-no {background-position: -96px -110px}
173 | .flag.flag-np {background-position: -112px -110px}
174 | .flag.flag-nr {background-position: -128px -110px}
175 | .flag.flag-nu {background-position: -144px -110px}
176 | .flag.flag-nz {background-position: -160px -110px}
177 | .flag.flag-om {background-position: -176px -110px}
178 | .flag.flag-pa {background-position: -192px -110px}
179 | .flag.flag-pe {background-position: -208px -110px}
180 | .flag.flag-pf {background-position: -224px -110px}
181 | .flag.flag-pg {background-position: -240px -110px}
182 | .flag.flag-ph {background-position: 0 -121px}
183 | .flag.flag-pk {background-position: -16px -121px}
184 | .flag.flag-pl {background-position: -32px -121px}
185 | .flag.flag-pm {background-position: -48px -121px}
186 | .flag.flag-pn {background-position: -64px -121px}
187 | .flag.flag-pr {background-position: -80px -121px}
188 | .flag.flag-ps {background-position: -96px -121px}
189 | .flag.flag-pt {background-position: -112px -121px}
190 | .flag.flag-pw {background-position: -128px -121px}
191 | .flag.flag-py {background-position: -144px -121px}
192 | .flag.flag-qa {background-position: -160px -121px}
193 | .flag.flag-re {background-position: -176px -121px}
194 | .flag.flag-ro {background-position: -192px -121px}
195 | .flag.flag-rs {background-position: -208px -121px}
196 | .flag.flag-ru {background-position: -224px -121px}
197 | .flag.flag-rw {background-position: -240px -121px}
198 | .flag.flag-sa {background-position: 0 -132px}
199 | .flag.flag-sb {background-position: -16px -132px}
200 | .flag.flag-sc {background-position: -32px -132px}
201 | .flag.flag-scotland {background-position: -48px -132px}
202 | .flag.flag-sd {background-position: -64px -132px}
203 | .flag.flag-se {background-position: -80px -132px}
204 | .flag.flag-sg {background-position: -96px -132px}
205 | .flag.flag-sh {background-position: -112px -132px}
206 | .flag.flag-si {background-position: -128px -132px}
207 | .flag.flag-sk {background-position: -144px -132px}
208 | .flag.flag-sl {background-position: -160px -132px}
209 | .flag.flag-sm {background-position: -176px -132px}
210 | .flag.flag-sn {background-position: -192px -132px}
211 | .flag.flag-so {background-position: -208px -132px}
212 | .flag.flag-somaliland {background-position: -224px -132px}
213 | .flag.flag-sr {background-position: -240px -132px}
214 | .flag.flag-ss {background-position: 0 -143px}
215 | .flag.flag-st {background-position: -16px -143px}
216 | .flag.flag-sv {background-position: -32px -143px}
217 | .flag.flag-sx {background-position: -48px -143px}
218 | .flag.flag-sy {background-position: -64px -143px}
219 | .flag.flag-sz {background-position: -80px -143px}
220 | .flag.flag-tc {background-position: -96px -143px}
221 | .flag.flag-td {background-position: -112px -143px}
222 | .flag.flag-tf {background-position: -128px -143px}
223 | .flag.flag-tg {background-position: -144px -143px}
224 | .flag.flag-th {background-position: -160px -143px}
225 | .flag.flag-tibet {background-position: -176px -143px}
226 | .flag.flag-tj {background-position: -192px -143px}
227 | .flag.flag-tk {background-position: -208px -143px}
228 | .flag.flag-tl {background-position: -224px -143px}
229 | .flag.flag-tm {background-position: -240px -143px}
230 | .flag.flag-tn {background-position: 0 -154px}
231 | .flag.flag-to {background-position: -16px -154px}
232 | .flag.flag-tr {background-position: -32px -154px}
233 | .flag.flag-tt {background-position: -48px -154px}
234 | .flag.flag-tv {background-position: -64px -154px}
235 | .flag.flag-tw {background-position: -80px -154px}
236 | .flag.flag-tz {background-position: -96px -154px}
237 | .flag.flag-ua {background-position: -112px -154px}
238 | .flag.flag-ug {background-position: -128px -154px}
239 | .flag.flag-um {background-position: -144px -154px}
240 | .flag.flag-us {background-position: -160px -154px}
241 | .flag.flag-uy {background-position: -176px -154px}
242 | .flag.flag-uz {background-position: -192px -154px}
243 | .flag.flag-va {background-position: -208px -154px}
244 | .flag.flag-vc {background-position: -224px -154px}
245 | .flag.flag-ve {background-position: -240px -154px}
246 | .flag.flag-vg {background-position: 0 -165px}
247 | .flag.flag-vi {background-position: -16px -165px}
248 | .flag.flag-vn {background-position: -32px -165px}
249 | .flag.flag-vu {background-position: -48px -165px}
250 | .flag.flag-wales {background-position: -64px -165px}
251 | .flag.flag-wf {background-position: -80px -165px}
252 | .flag.flag-ws {background-position: -96px -165px}
253 | .flag.flag-xk {background-position: -112px -165px}
254 | .flag.flag-ye {background-position: -128px -165px}
255 | .flag.flag-yt {background-position: -144px -165px}
256 | .flag.flag-za {background-position: -160px -165px}
257 | .flag.flag-zanzibar {background-position: -176px -165px}
258 | .flag.flag-zm {background-position: -192px -165px}
259 | .flag.flag-zw {background-position: -208px -165px}
260 |
--------------------------------------------------------------------------------
/servers/portforward/theme/flags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TachibanaSuzume/WhmcsPortForward/ebdbb8119bd8d3604636a5b99a57c6ff20c27f4d/servers/portforward/theme/flags.png
--------------------------------------------------------------------------------
/servers/portforward/theme/jquery-confirm.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * jquery-confirm v3.2.3 (http://craftpip.github.io/jquery-confirm/)
3 | * Author: boniface pereira
4 | * Website: www.craftpip.com
5 | * Contact: hey@craftpip.com
6 | *
7 | * Copyright 2013-2017 jquery-confirm
8 | * Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
9 | */
10 | @-webkit-keyframes jconfirm-spin {
11 | from {
12 | -webkit-transform: rotate(0deg);
13 | transform: rotate(0deg);
14 | }
15 | to {
16 | -webkit-transform: rotate(360deg);
17 | transform: rotate(360deg);
18 | }
19 | }
20 | @keyframes jconfirm-spin {
21 | from {
22 | -webkit-transform: rotate(0deg);
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | -webkit-transform: rotate(360deg);
27 | transform: rotate(360deg);
28 | }
29 | }
30 | body[class*=jconfirm-no-scroll-] {
31 | overflow: hidden !important;
32 | }
33 | .jconfirm {
34 | position: fixed;
35 | top: 0;
36 | left: 0;
37 | right: 0;
38 | bottom: 0;
39 | z-index: 99999999;
40 | font-family: inherit;
41 | overflow: hidden;
42 | }
43 | .jconfirm .jconfirm-bg {
44 | position: fixed;
45 | top: 0;
46 | left: 0;
47 | right: 0;
48 | bottom: 0;
49 | -webkit-transition: opacity .4s;
50 | transition: opacity .4s;
51 | }
52 | .jconfirm .jconfirm-bg.jconfirm-bg-h {
53 | opacity: 0 !important;
54 | }
55 | .jconfirm .jconfirm-scrollpane {
56 | position: fixed;
57 | top: 0;
58 | left: 0;
59 | right: 0;
60 | bottom: 0;
61 | overflow-y: auto;
62 | -webkit-perspective: 500px;
63 | perspective: 500px;
64 | -webkit-perspective-origin: center;
65 | perspective-origin: center;
66 | }
67 | .jconfirm .jconfirm-box {
68 | background: white;
69 | border-radius: 4px;
70 | position: relative;
71 | outline: none;
72 | padding: 15px 15px 0;
73 | overflow: hidden;
74 | margin-left: auto;
75 | margin-right: auto;
76 | }
77 | @-webkit-keyframes type-blue {
78 | 1%,
79 | 100% {
80 | border-color: #3498db;
81 | }
82 | 50% {
83 | border-color: #5faee3;
84 | }
85 | }
86 | @keyframes type-blue {
87 | 1%,
88 | 100% {
89 | border-color: #3498db;
90 | }
91 | 50% {
92 | border-color: #5faee3;
93 | }
94 | }
95 | @-webkit-keyframes type-green {
96 | 1%,
97 | 100% {
98 | border-color: #2ecc71;
99 | }
100 | 50% {
101 | border-color: #54d98c;
102 | }
103 | }
104 | @keyframes type-green {
105 | 1%,
106 | 100% {
107 | border-color: #2ecc71;
108 | }
109 | 50% {
110 | border-color: #54d98c;
111 | }
112 | }
113 | @-webkit-keyframes type-red {
114 | 1%,
115 | 100% {
116 | border-color: #e74c3c;
117 | }
118 | 50% {
119 | border-color: #ed7669;
120 | }
121 | }
122 | @keyframes type-red {
123 | 1%,
124 | 100% {
125 | border-color: #e74c3c;
126 | }
127 | 50% {
128 | border-color: #ed7669;
129 | }
130 | }
131 | @-webkit-keyframes type-orange {
132 | 1%,
133 | 100% {
134 | border-color: #f1c40f;
135 | }
136 | 50% {
137 | border-color: #f4d03f;
138 | }
139 | }
140 | @keyframes type-orange {
141 | 1%,
142 | 100% {
143 | border-color: #f1c40f;
144 | }
145 | 50% {
146 | border-color: #f4d03f;
147 | }
148 | }
149 | @-webkit-keyframes type-purple {
150 | 1%,
151 | 100% {
152 | border-color: #9b59b6;
153 | }
154 | 50% {
155 | border-color: #b07cc6;
156 | }
157 | }
158 | @keyframes type-purple {
159 | 1%,
160 | 100% {
161 | border-color: #9b59b6;
162 | }
163 | 50% {
164 | border-color: #b07cc6;
165 | }
166 | }
167 | @-webkit-keyframes type-dark {
168 | 1%,
169 | 100% {
170 | border-color: #34495e;
171 | }
172 | 50% {
173 | border-color: #46627f;
174 | }
175 | }
176 | @keyframes type-dark {
177 | 1%,
178 | 100% {
179 | border-color: #34495e;
180 | }
181 | 50% {
182 | border-color: #46627f;
183 | }
184 | }
185 | .jconfirm .jconfirm-box.jconfirm-type-animated {
186 | -webkit-animation-duration: 2s;
187 | animation-duration: 2s;
188 | -webkit-animation-iteration-count: infinite;
189 | animation-iteration-count: infinite;
190 | }
191 | .jconfirm .jconfirm-box.jconfirm-type-blue {
192 | border-top: solid 7px #3498db;
193 | -webkit-animation-name: type-blue;
194 | animation-name: type-blue;
195 | }
196 | .jconfirm .jconfirm-box.jconfirm-type-green {
197 | border-top: solid 7px #2ecc71;
198 | -webkit-animation-name: type-green;
199 | animation-name: type-green;
200 | }
201 | .jconfirm .jconfirm-box.jconfirm-type-red {
202 | border-top: solid 7px #e74c3c;
203 | -webkit-animation-name: type-red;
204 | animation-name: type-red;
205 | }
206 | .jconfirm .jconfirm-box.jconfirm-type-orange {
207 | border-top: solid 7px #f1c40f;
208 | -webkit-animation-name: type-orange;
209 | animation-name: type-orange;
210 | }
211 | .jconfirm .jconfirm-box.jconfirm-type-purple {
212 | border-top: solid 7px #9b59b6;
213 | -webkit-animation-name: type-purple;
214 | animation-name: type-purple;
215 | }
216 | .jconfirm .jconfirm-box.jconfirm-type-dark {
217 | border-top: solid 7px #34495e;
218 | -webkit-animation-name: type-dark;
219 | animation-name: type-dark;
220 | }
221 | .jconfirm .jconfirm-box.loading {
222 | height: 120px;
223 | }
224 | .jconfirm .jconfirm-box.loading:before {
225 | content: '';
226 | position: absolute;
227 | left: 0;
228 | background: white;
229 | right: 0;
230 | top: 0;
231 | bottom: 0;
232 | border-radius: 10px;
233 | z-index: 1;
234 | }
235 | .jconfirm .jconfirm-box.loading:after {
236 | opacity: 0.6;
237 | content: '';
238 | height: 30px;
239 | width: 30px;
240 | border: solid 3px transparent;
241 | position: absolute;
242 | left: 50%;
243 | margin-left: -15px;
244 | border-radius: 50%;
245 | -webkit-animation: jconfirm-spin 1s infinite linear;
246 | animation: jconfirm-spin 1s infinite linear;
247 | border-bottom-color: dodgerblue;
248 | top: 50%;
249 | margin-top: -15px;
250 | z-index: 2;
251 | }
252 | .jconfirm .jconfirm-box div.jconfirm-closeIcon {
253 | height: 20px;
254 | width: 20px;
255 | position: absolute;
256 | top: 5px;
257 | right: 5px;
258 | cursor: pointer;
259 | opacity: .6;
260 | text-align: center;
261 | -webkit-transition: opacity 0.3s ease-in;
262 | transition: opacity 0.3s ease-in;
263 | font-size: 27px !important;
264 | line-height: 14px !important;
265 | display: none;
266 | }
267 | .jconfirm .jconfirm-box div.jconfirm-closeIcon:empty {
268 | display: none;
269 | }
270 | .jconfirm .jconfirm-box div.jconfirm-closeIcon .fa {
271 | font-size: 16px;
272 | }
273 | .jconfirm .jconfirm-box div.jconfirm-closeIcon .glyphicon {
274 | font-size: 16px;
275 | }
276 | .jconfirm .jconfirm-box div.jconfirm-closeIcon .zmdi {
277 | font-size: 16px;
278 | }
279 | .jconfirm .jconfirm-box div.jconfirm-closeIcon:hover {
280 | opacity: 1;
281 | }
282 | .jconfirm .jconfirm-box div.jconfirm-title-c {
283 | display: block;
284 | font-size: 22px;
285 | line-height: 20px;
286 | -webkit-user-select: none;
287 | -moz-user-select: none;
288 | -ms-user-select: none;
289 | user-select: none;
290 | }
291 | .jconfirm .jconfirm-box div.jconfirm-title-c.jconfirm-hand {
292 | cursor: move;
293 | }
294 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
295 | font-size: inherit;
296 | padding-bottom: 15px;
297 | display: inline-block;
298 | vertical-align: middle;
299 | }
300 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c i {
301 | vertical-align: middle;
302 | }
303 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c:empty {
304 | display: none;
305 | }
306 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-title {
307 | -webkit-user-select: none;
308 | -moz-user-select: none;
309 | -ms-user-select: none;
310 | user-select: none;
311 | font-size: inherit;
312 | font-family: inherit;
313 | display: inline-block;
314 | vertical-align: middle;
315 | padding-bottom: 15px;
316 | }
317 | .jconfirm .jconfirm-box div.jconfirm-title-c .jconfirm-title:empty {
318 | display: none;
319 | }
320 | .jconfirm .jconfirm-box div.jconfirm-content-pane {
321 | margin-bottom: 15px;
322 | height: auto;
323 | -webkit-transition: height 0.4s ease-in;
324 | transition: height 0.4s ease-in;
325 | display: inline-block;
326 | width: 100%;
327 | position: relative;
328 | overflow: hidden;
329 | }
330 | .jconfirm .jconfirm-box div.jconfirm-content-pane .jconfirm-content img {
331 | max-width: 100%;
332 | height: auto;
333 | }
334 | .jconfirm .jconfirm-box div.jconfirm-content-pane .jconfirm-content:empty {
335 | display: none;
336 | }
337 | .jconfirm .jconfirm-box .jconfirm-buttons {
338 | padding-bottom: 11px;
339 | }
340 | .jconfirm .jconfirm-box .jconfirm-buttons > button {
341 | margin-bottom: 4px;
342 | margin-left: 2px;
343 | margin-right: 2px;
344 | }
345 | .jconfirm .jconfirm-box .jconfirm-buttons button {
346 | display: inline-block;
347 | padding: 6px 12px;
348 | font-size: 14px;
349 | font-weight: 400;
350 | line-height: 1.42857143;
351 | text-align: center;
352 | white-space: nowrap;
353 | vertical-align: middle;
354 | -ms-touch-action: manipulation;
355 | touch-action: manipulation;
356 | cursor: pointer;
357 | -webkit-user-select: none;
358 | -moz-user-select: none;
359 | -ms-user-select: none;
360 | border-radius: 4px;
361 | min-height: 1em;
362 | outline: 0;
363 | -webkit-user-select: none;
364 | -moz-user-select: none;
365 | -ms-user-select: none;
366 | user-select: none;
367 | -webkit-transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
368 | transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
369 | -webkit-tap-highlight-color: transparent;
370 | border: none;
371 | background-image: none;
372 | }
373 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-blue {
374 | background-color: #3498db;
375 | color: #FFF;
376 | text-shadow: none;
377 | -webkit-transition: background .2s;
378 | transition: background .2s;
379 | }
380 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-blue:hover {
381 | background-color: #2980b9;
382 | color: #FFF;
383 | }
384 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-green {
385 | background-color: #2ecc71;
386 | color: #FFF;
387 | text-shadow: none;
388 | -webkit-transition: background .2s;
389 | transition: background .2s;
390 | }
391 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-green:hover {
392 | background-color: #27ae60;
393 | color: #FFF;
394 | }
395 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-red {
396 | background-color: #e74c3c;
397 | color: #FFF;
398 | text-shadow: none;
399 | -webkit-transition: background .2s;
400 | transition: background .2s;
401 | }
402 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-red:hover {
403 | background-color: #c0392b;
404 | color: #FFF;
405 | }
406 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-orange {
407 | background-color: #f1c40f;
408 | color: #FFF;
409 | text-shadow: none;
410 | -webkit-transition: background .2s;
411 | transition: background .2s;
412 | }
413 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-orange:hover {
414 | background-color: #f39c12;
415 | color: #FFF;
416 | }
417 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-default {
418 | background-color: #ecf0f1;
419 | color: #000;
420 | text-shadow: none;
421 | -webkit-transition: background .2s;
422 | transition: background .2s;
423 | }
424 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-default:hover {
425 | background-color: #bdc3c7;
426 | color: #000;
427 | }
428 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-purple {
429 | background-color: #9b59b6;
430 | color: #FFF;
431 | text-shadow: none;
432 | -webkit-transition: background .2s;
433 | transition: background .2s;
434 | }
435 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-purple:hover {
436 | background-color: #8e44ad;
437 | color: #FFF;
438 | }
439 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-dark {
440 | background-color: #34495e;
441 | color: #FFF;
442 | text-shadow: none;
443 | -webkit-transition: background .2s;
444 | transition: background .2s;
445 | }
446 | .jconfirm .jconfirm-box .jconfirm-buttons button.btn-dark:hover {
447 | background-color: #2c3e50;
448 | color: #FFF;
449 | }
450 | .jconfirm .jconfirm-box.jconfirm-type-red .jconfirm-title-c .jconfirm-icon-c {
451 | color: #e74c3c !important;
452 | }
453 | .jconfirm .jconfirm-box.jconfirm-type-blue .jconfirm-title-c .jconfirm-icon-c {
454 | color: #3498db !important;
455 | }
456 | .jconfirm .jconfirm-box.jconfirm-type-green .jconfirm-title-c .jconfirm-icon-c {
457 | color: #2ecc71 !important;
458 | }
459 | .jconfirm .jconfirm-box.jconfirm-type-purple .jconfirm-title-c .jconfirm-icon-c {
460 | color: #9b59b6 !important;
461 | }
462 | .jconfirm .jconfirm-box.jconfirm-type-orange .jconfirm-title-c .jconfirm-icon-c {
463 | color: #f1c40f !important;
464 | }
465 | .jconfirm .jconfirm-box.jconfirm-type-dark .jconfirm-title-c .jconfirm-icon-c {
466 | color: #34495e !important;
467 | }
468 | .jconfirm .jconfirm-clear {
469 | clear: both;
470 | }
471 | .jconfirm.jconfirm-rtl {
472 | direction: rtl;
473 | }
474 | .jconfirm.jconfirm-rtl div.jconfirm-closeIcon {
475 | left: 5px;
476 | right: auto;
477 | }
478 | .jconfirm.jconfirm-white .jconfirm-bg,
479 | .jconfirm.jconfirm-light .jconfirm-bg {
480 | background-color: #444;
481 | opacity: .2;
482 | }
483 | .jconfirm.jconfirm-white .jconfirm-box,
484 | .jconfirm.jconfirm-light .jconfirm-box {
485 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
486 | border-radius: 5px;
487 | }
488 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-title-c .jconfirm-icon-c,
489 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
490 | margin-right: 8px;
491 | margin-left: 0px;
492 | }
493 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons,
494 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons {
495 | float: right;
496 | }
497 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons button,
498 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons button {
499 | text-transform: uppercase;
500 | font-size: 14px;
501 | font-weight: bold;
502 | text-shadow: none;
503 | }
504 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons button.btn-default,
505 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons button.btn-default {
506 | box-shadow: none;
507 | color: #333;
508 | }
509 | .jconfirm.jconfirm-white .jconfirm-box .jconfirm-buttons button.btn-default:hover,
510 | .jconfirm.jconfirm-light .jconfirm-box .jconfirm-buttons button.btn-default:hover {
511 | background: #ddd;
512 | }
513 | .jconfirm.jconfirm-white.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c,
514 | .jconfirm.jconfirm-light.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
515 | margin-left: 8px;
516 | margin-right: 0px;
517 | }
518 | .jconfirm.jconfirm-black .jconfirm-bg,
519 | .jconfirm.jconfirm-dark .jconfirm-bg {
520 | background-color: darkslategray;
521 | opacity: .4;
522 | }
523 | .jconfirm.jconfirm-black .jconfirm-box,
524 | .jconfirm.jconfirm-dark .jconfirm-box {
525 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
526 | background: #444;
527 | border-radius: 5px;
528 | color: white;
529 | }
530 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-title-c .jconfirm-icon-c,
531 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
532 | margin-right: 8px;
533 | margin-left: 0px;
534 | }
535 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons,
536 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons {
537 | float: right;
538 | }
539 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons button,
540 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons button {
541 | border: none;
542 | background-image: none;
543 | text-transform: uppercase;
544 | font-size: 14px;
545 | font-weight: bold;
546 | text-shadow: none;
547 | -webkit-transition: background .1s;
548 | transition: background .1s;
549 | color: white;
550 | }
551 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons button.btn-default,
552 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons button.btn-default {
553 | box-shadow: none;
554 | color: #fff;
555 | background: none;
556 | }
557 | .jconfirm.jconfirm-black .jconfirm-box .jconfirm-buttons button.btn-default:hover,
558 | .jconfirm.jconfirm-dark .jconfirm-box .jconfirm-buttons button.btn-default:hover {
559 | background: #666;
560 | }
561 | .jconfirm.jconfirm-black.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c,
562 | .jconfirm.jconfirm-dark.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
563 | margin-left: 8px;
564 | margin-right: 0px;
565 | }
566 | .jconfirm .jconfirm-box.hilight.jconfirm-hilight-shake {
567 | -webkit-animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
568 | animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
569 | -webkit-transform: translate3d(0, 0, 0);
570 | transform: translate3d(0, 0, 0);
571 | }
572 | .jconfirm .jconfirm-box.hilight.jconfirm-hilight-glow {
573 | -webkit-animation: glow 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
574 | animation: glow 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
575 | -webkit-transform: translate3d(0, 0, 0);
576 | transform: translate3d(0, 0, 0);
577 | }
578 | @-webkit-keyframes shake {
579 | 10%,
580 | 90% {
581 | -webkit-transform: translate3d(-2px, 0, 0);
582 | transform: translate3d(-2px, 0, 0);
583 | }
584 | 20%,
585 | 80% {
586 | -webkit-transform: translate3d(4px, 0, 0);
587 | transform: translate3d(4px, 0, 0);
588 | }
589 | 30%,
590 | 50%,
591 | 70% {
592 | -webkit-transform: translate3d(-8px, 0, 0);
593 | transform: translate3d(-8px, 0, 0);
594 | }
595 | 40%,
596 | 60% {
597 | -webkit-transform: translate3d(8px, 0, 0);
598 | transform: translate3d(8px, 0, 0);
599 | }
600 | }
601 | @keyframes shake {
602 | 10%,
603 | 90% {
604 | -webkit-transform: translate3d(-2px, 0, 0);
605 | transform: translate3d(-2px, 0, 0);
606 | }
607 | 20%,
608 | 80% {
609 | -webkit-transform: translate3d(4px, 0, 0);
610 | transform: translate3d(4px, 0, 0);
611 | }
612 | 30%,
613 | 50%,
614 | 70% {
615 | -webkit-transform: translate3d(-8px, 0, 0);
616 | transform: translate3d(-8px, 0, 0);
617 | }
618 | 40%,
619 | 60% {
620 | -webkit-transform: translate3d(8px, 0, 0);
621 | transform: translate3d(8px, 0, 0);
622 | }
623 | }
624 | @-webkit-keyframes glow {
625 | 0%,
626 | 100% {
627 | box-shadow: 0 0 3px red;
628 | }
629 | 50% {
630 | box-shadow: 0 0 30px red;
631 | }
632 | }
633 | @keyframes glow {
634 | 0%,
635 | 100% {
636 | box-shadow: 0 0 3px red;
637 | }
638 | 50% {
639 | box-shadow: 0 0 30px red;
640 | }
641 | }
642 | /*Transition rules*/
643 | .jconfirm {
644 | -webkit-perspective: 400px;
645 | perspective: 400px;
646 | }
647 | .jconfirm .jconfirm-box {
648 | opacity: 1;
649 | -webkit-transition-property: all;
650 | transition-property: all;
651 | }
652 | .jconfirm .jconfirm-box.jconfirm-animation-top,
653 | .jconfirm .jconfirm-box.jconfirm-animation-left,
654 | .jconfirm .jconfirm-box.jconfirm-animation-right,
655 | .jconfirm .jconfirm-box.jconfirm-animation-bottom,
656 | .jconfirm .jconfirm-box.jconfirm-animation-opacity,
657 | .jconfirm .jconfirm-box.jconfirm-animation-zoom,
658 | .jconfirm .jconfirm-box.jconfirm-animation-scale,
659 | .jconfirm .jconfirm-box.jconfirm-animation-none,
660 | .jconfirm .jconfirm-box.jconfirm-animation-rotate,
661 | .jconfirm .jconfirm-box.jconfirm-animation-rotatex,
662 | .jconfirm .jconfirm-box.jconfirm-animation-rotatey,
663 | .jconfirm .jconfirm-box.jconfirm-animation-scaley,
664 | .jconfirm .jconfirm-box.jconfirm-animation-scalex {
665 | opacity: 0;
666 | }
667 | .jconfirm .jconfirm-box.jconfirm-animation-rotate {
668 | -webkit-transform: rotate(90deg);
669 | -ms-transform: rotate(90deg);
670 | transform: rotate(90deg);
671 | }
672 | .jconfirm .jconfirm-box.jconfirm-animation-rotatex {
673 | -webkit-transform: rotateX(90deg);
674 | transform: rotateX(90deg);
675 | -webkit-transform-origin: center;
676 | -ms-transform-origin: center;
677 | transform-origin: center;
678 | }
679 | .jconfirm .jconfirm-box.jconfirm-animation-rotatexr {
680 | -webkit-transform: rotateX(-90deg);
681 | transform: rotateX(-90deg);
682 | -webkit-transform-origin: center;
683 | -ms-transform-origin: center;
684 | transform-origin: center;
685 | }
686 | .jconfirm .jconfirm-box.jconfirm-animation-rotatey {
687 | -webkit-transform: rotatey(90deg);
688 | -ms-transform: rotatey(90deg);
689 | transform: rotatey(90deg);
690 | -webkit-transform-origin: center;
691 | -ms-transform-origin: center;
692 | transform-origin: center;
693 | }
694 | .jconfirm .jconfirm-box.jconfirm-animation-rotateyr {
695 | -webkit-transform: rotatey(-90deg);
696 | -ms-transform: rotatey(-90deg);
697 | transform: rotatey(-90deg);
698 | -webkit-transform-origin: center;
699 | -ms-transform-origin: center;
700 | transform-origin: center;
701 | }
702 | .jconfirm .jconfirm-box.jconfirm-animation-scaley {
703 | -webkit-transform: scaley(1.5);
704 | -ms-transform: scaley(1.5);
705 | transform: scaley(1.5);
706 | -webkit-transform-origin: center;
707 | -ms-transform-origin: center;
708 | transform-origin: center;
709 | }
710 | .jconfirm .jconfirm-box.jconfirm-animation-scalex {
711 | -webkit-transform: scalex(1.5);
712 | -ms-transform: scalex(1.5);
713 | transform: scalex(1.5);
714 | -webkit-transform-origin: center;
715 | -ms-transform-origin: center;
716 | transform-origin: center;
717 | }
718 | .jconfirm .jconfirm-box.jconfirm-animation-top {
719 | -webkit-transform: translate(0px, -100px);
720 | -ms-transform: translate(0px, -100px);
721 | transform: translate(0px, -100px);
722 | }
723 | .jconfirm .jconfirm-box.jconfirm-animation-left {
724 | -webkit-transform: translate(-100px, 0px);
725 | -ms-transform: translate(-100px, 0px);
726 | transform: translate(-100px, 0px);
727 | }
728 | .jconfirm .jconfirm-box.jconfirm-animation-right {
729 | -webkit-transform: translate(100px, 0px);
730 | -ms-transform: translate(100px, 0px);
731 | transform: translate(100px, 0px);
732 | }
733 | .jconfirm .jconfirm-box.jconfirm-animation-bottom {
734 | -webkit-transform: translate(0px, 100px);
735 | -ms-transform: translate(0px, 100px);
736 | transform: translate(0px, 100px);
737 | }
738 | .jconfirm .jconfirm-box.jconfirm-animation-zoom {
739 | -webkit-transform: scale(1.2);
740 | -ms-transform: scale(1.2);
741 | transform: scale(1.2);
742 | }
743 | .jconfirm .jconfirm-box.jconfirm-animation-scale {
744 | -webkit-transform: scale(0.5);
745 | -ms-transform: scale(0.5);
746 | transform: scale(0.5);
747 | }
748 | .jconfirm .jconfirm-box.jconfirm-animation-none {
749 | visibility: hidden;
750 | }
751 | .jconfirm.jconfirm-supervan .jconfirm-bg {
752 | background-color: rgba(54, 70, 93, 0.95);
753 | }
754 | .jconfirm.jconfirm-supervan .jconfirm-box {
755 | background-color: transparent;
756 | }
757 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-blue {
758 | border: none;
759 | }
760 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-green {
761 | border: none;
762 | }
763 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-red {
764 | border: none;
765 | }
766 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-orange {
767 | border: none;
768 | }
769 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-purple {
770 | border: none;
771 | }
772 | .jconfirm.jconfirm-supervan .jconfirm-box.jconfirm-type-dark {
773 | border: none;
774 | }
775 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-closeIcon {
776 | color: white;
777 | }
778 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-title-c {
779 | text-align: center;
780 | color: white;
781 | font-size: 28px;
782 | font-weight: normal;
783 | }
784 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-title-c > * {
785 | padding-bottom: 25px;
786 | }
787 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
788 | margin-right: 8px;
789 | margin-left: 0px;
790 | }
791 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-content-pane {
792 | margin-bottom: 25px;
793 | }
794 | .jconfirm.jconfirm-supervan .jconfirm-box div.jconfirm-content {
795 | text-align: center;
796 | color: white;
797 | }
798 | .jconfirm.jconfirm-supervan .jconfirm-box .jconfirm-buttons {
799 | text-align: center;
800 | }
801 | .jconfirm.jconfirm-supervan .jconfirm-box .jconfirm-buttons button {
802 | font-size: 16px;
803 | border-radius: 2px;
804 | background: #303f53;
805 | text-shadow: none;
806 | border: none;
807 | color: white;
808 | padding: 10px;
809 | min-width: 100px;
810 | }
811 | .jconfirm.jconfirm-supervan.jconfirm-rtl .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
812 | margin-left: 8px;
813 | margin-right: 0px;
814 | }
815 | .jconfirm.jconfirm-material .jconfirm-bg {
816 | background-color: rgba(0, 0, 0, 0.67);
817 | }
818 | .jconfirm.jconfirm-material .jconfirm-box {
819 | background-color: white;
820 | box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
821 | padding: 30px 25px 10px 25px;
822 | }
823 | .jconfirm.jconfirm-material .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
824 | margin-right: 8px;
825 | margin-left: 0px;
826 | }
827 | .jconfirm.jconfirm-material .jconfirm-box div.jconfirm-closeIcon {
828 | color: rgba(0, 0, 0, 0.87);
829 | }
830 | .jconfirm.jconfirm-material .jconfirm-box div.jconfirm-title-c {
831 | color: rgba(0, 0, 0, 0.87);
832 | font-size: 22px;
833 | font-weight: bold;
834 | }
835 | .jconfirm.jconfirm-material .jconfirm-box div.jconfirm-content {
836 | color: rgba(0, 0, 0, 0.87);
837 | }
838 | .jconfirm.jconfirm-material .jconfirm-box .jconfirm-buttons {
839 | text-align: right;
840 | }
841 | .jconfirm.jconfirm-material .jconfirm-box .jconfirm-buttons button {
842 | text-transform: uppercase;
843 | font-weight: 500;
844 | }
845 | .jconfirm.jconfirm-material.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
846 | margin-left: 8px;
847 | margin-right: 0px;
848 | }
849 | .jconfirm.jconfirm-bootstrap .jconfirm-bg {
850 | background-color: rgba(0, 0, 0, 0.21);
851 | }
852 | .jconfirm.jconfirm-bootstrap .jconfirm-box {
853 | background-color: white;
854 | box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.2);
855 | border: solid 1px rgba(0, 0, 0, 0.4);
856 | padding: 15px 0 0;
857 | }
858 | .jconfirm.jconfirm-bootstrap .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
859 | margin-right: 8px;
860 | margin-left: 0px;
861 | }
862 | .jconfirm.jconfirm-bootstrap .jconfirm-box div.jconfirm-closeIcon {
863 | color: rgba(0, 0, 0, 0.87);
864 | }
865 | .jconfirm.jconfirm-bootstrap .jconfirm-box div.jconfirm-title-c {
866 | color: rgba(0, 0, 0, 0.87);
867 | font-size: 22px;
868 | font-weight: bold;
869 | padding-left: 15px;
870 | padding-right: 15px;
871 | }
872 | .jconfirm.jconfirm-bootstrap .jconfirm-box div.jconfirm-content {
873 | color: rgba(0, 0, 0, 0.87);
874 | padding: 0px 15px;
875 | }
876 | .jconfirm.jconfirm-bootstrap .jconfirm-box .jconfirm-buttons {
877 | text-align: right;
878 | padding: 10px;
879 | margin: -5px 0 0px;
880 | border-top: solid 1px #ddd;
881 | overflow: hidden;
882 | border-radius: 0 0 4px 4px;
883 | }
884 | .jconfirm.jconfirm-bootstrap .jconfirm-box .jconfirm-buttons button {
885 | font-weight: 500;
886 | }
887 | .jconfirm.jconfirm-bootstrap.jconfirm-rtl .jconfirm-title-c .jconfirm-icon-c {
888 | margin-left: 8px;
889 | margin-right: 0px;
890 | }
891 | .jconfirm.jconfirm-modern .jconfirm-bg {
892 | background-color: slategray;
893 | opacity: .6;
894 | }
895 | .jconfirm.jconfirm-modern .jconfirm-box {
896 | background-color: white;
897 | box-shadow: 0 7px 8px -4px rgba(0, 0, 0, 0.2), 0 13px 19px 2px rgba(0, 0, 0, 0.14), 0 5px 24px 4px rgba(0, 0, 0, 0.12);
898 | padding: 30px 30px 15px;
899 | }
900 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-closeIcon {
901 | color: rgba(0, 0, 0, 0.87);
902 | top: 15px;
903 | right: 15px;
904 | }
905 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-title-c {
906 | color: rgba(0, 0, 0, 0.87);
907 | font-size: 24px;
908 | font-weight: bold;
909 | text-align: center;
910 | margin-bottom: 10px;
911 | }
912 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-title-c .jconfirm-icon-c {
913 | -webkit-transition: -webkit-transform .5s;
914 | transition: transform .5s;
915 | -webkit-transform: scale(0);
916 | -ms-transform: scale(0);
917 | transform: scale(0);
918 | display: block;
919 | margin-right: 0px;
920 | margin-left: 0px;
921 | margin-bottom: 10px;
922 | font-size: 69px;
923 | color: #aaa;
924 | }
925 | .jconfirm.jconfirm-modern .jconfirm-box div.jconfirm-content {
926 | text-align: center;
927 | font-size: 15px;
928 | color: #777;
929 | margin-bottom: 25px;
930 | }
931 | .jconfirm.jconfirm-modern .jconfirm-box .jconfirm-buttons {
932 | text-align: center;
933 | }
934 | .jconfirm.jconfirm-modern .jconfirm-box .jconfirm-buttons button {
935 | font-weight: bold;
936 | text-transform: uppercase;
937 | -webkit-transition: background .1s;
938 | transition: background .1s;
939 | padding: 10px 20px;
940 | }
941 | .jconfirm.jconfirm-modern .jconfirm-box .jconfirm-buttons button + button {
942 | margin-left: 4px;
943 | }
944 | .jconfirm.jconfirm-modern.jconfirm-open .jconfirm-box .jconfirm-title-c .jconfirm-icon-c {
945 | -webkit-transform: scale(1);
946 | -ms-transform: scale(1);
947 | transform: scale(1);
948 | }
949 |
--------------------------------------------------------------------------------
/servers/portforward/theme/jquery-confirm.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jquery-confirm v3.2.3 (http://craftpip.github.io/jquery-confirm/)
3 | * Author: Boniface Pereira
4 | * Website: www.craftpip.com
5 | * Contact: hey@craftpip.com
6 | *
7 | * Copyright 2013-2017 jquery-confirm
8 | * Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
9 | */
10 |
11 | if (typeof jQuery === 'undefined') {
12 | throw new Error('jquery-confirm requires jQuery');
13 | }
14 |
15 | var jconfirm, Jconfirm;
16 | (function ($, window) {
17 | "use strict";
18 |
19 | $.fn.confirm = function (options, option2) {
20 | if (typeof options === 'undefined') options = {};
21 | if (typeof options === 'string') {
22 | options = {
23 | content: options,
24 | title: (option2) ? option2 : false
25 | };
26 | }
27 | /*
28 | * Alias of $.confirm to emulate native confirm()
29 | */
30 | $(this).each(function () {
31 | var $this = $(this);
32 | $this.on('click', function (e) {
33 | e.preventDefault();
34 | var jcOption = $.extend({}, options);
35 | if ($this.attr('data-title'))
36 | jcOption['title'] = $this.attr('data-title');
37 | if ($this.attr('data-content'))
38 | jcOption['content'] = $this.attr('data-content');
39 | if (typeof jcOption['buttons'] == 'undefined')
40 | jcOption['buttons'] = {};
41 |
42 | jcOption['$target'] = $this;
43 | if ($this.attr('href') && Object.keys(jcOption['buttons']).length == 0) {
44 | var buttons = $.extend(true, {}, jconfirm.pluginDefaults.defaultButtons, (jconfirm.defaults || {}).defaultButtons || {});
45 | var firstBtn = Object.keys(buttons)[0];
46 | jcOption['buttons'] = buttons;
47 | jcOption.buttons[firstBtn].action = function () {
48 | location.href = $this.attr('href');
49 | };
50 | }
51 | jcOption['closeIcon'] = false;
52 | $.confirm(jcOption);
53 | });
54 | });
55 | return $(this);
56 | };
57 | $.confirm = function (options, option2) {
58 | if (typeof options === 'undefined') options = {};
59 | if (typeof options === 'string') {
60 | options = {
61 | content: options,
62 | title: (option2) ? option2 : false
63 | };
64 | }
65 |
66 | if (typeof options['buttons'] != 'object')
67 | options['buttons'] = {};
68 |
69 | if (Object.keys(options['buttons']).length == 0) {
70 | var buttons = $.extend(true, {}, jconfirm.pluginDefaults.defaultButtons, (jconfirm.defaults || {}).defaultButtons || {});
71 | options['buttons'] = buttons;
72 | }
73 |
74 | /*
75 | * Alias of jconfirm
76 | */
77 | return jconfirm(options);
78 | };
79 | $.alert = function (options, option2) {
80 | if (typeof options === 'undefined') options = {};
81 | if (typeof options === 'string') {
82 | options = {
83 | content: options,
84 | title: (option2) ? option2 : false
85 | };
86 | }
87 |
88 | if (typeof options.buttons != 'object')
89 | options.buttons = {};
90 |
91 | if (Object.keys(options['buttons']).length == 0) {
92 | var buttons = $.extend(true, {}, jconfirm.pluginDefaults.defaultButtons, (jconfirm.defaults || {}).defaultButtons || {});
93 | var firstBtn = Object.keys(buttons)[0];
94 | options['buttons'][firstBtn] = buttons[firstBtn];
95 | }
96 | /*
97 | * Alias of jconfirm
98 | */
99 | return jconfirm(options);
100 | };
101 | $.dialog = function (options, option2) {
102 | if (typeof options === 'undefined') options = {};
103 | if (typeof options === 'string') {
104 | options = {
105 | content: options,
106 | title: (option2) ? option2 : false,
107 | closeIcon: function () {
108 | // Just close the modal
109 | }
110 | };
111 | }
112 |
113 | options['buttons'] = {}; // purge buttons
114 |
115 | if (typeof options['closeIcon'] == 'undefined') {
116 | // Dialog must have a closeIcon.
117 | options['closeIcon'] = function () {
118 | }
119 | }
120 | /*
121 | * Alias of jconfirm
122 | */
123 | options.confirmKeys = [13];
124 | return jconfirm(options);
125 | };
126 |
127 | jconfirm = function (options) {
128 | if (typeof options === 'undefined') options = {};
129 | /*
130 | * initial function for calling.
131 | */
132 | var pluginOptions = $.extend(true, {}, jconfirm.pluginDefaults);
133 | if (jconfirm.defaults) {
134 | pluginOptions = $.extend(true, pluginOptions, jconfirm.defaults);
135 | }
136 |
137 | /*
138 | * merge options with plugin defaults.
139 | */
140 | pluginOptions = $.extend(true, {}, pluginOptions, options);
141 | var instance = new Jconfirm(pluginOptions);
142 | jconfirm.instances.push(instance);
143 | return instance;
144 | };
145 | Jconfirm = function (options) {
146 | /*
147 | * constructor function Jconfirm,
148 | * options = user options.
149 | */
150 | $.extend(this, options);
151 | this._init();
152 | };
153 | Jconfirm.prototype = {
154 | _init: function () {
155 | var that = this;
156 |
157 | if (!jconfirm.instances.length)
158 | jconfirm.lastFocused = $('body').find(':focus');
159 |
160 | this._id = Math.round(Math.random() * 99999);
161 |
162 | if (!this.lazyOpen) {
163 | setTimeout(function () {
164 | that.open();
165 | }, 0);
166 | }
167 | },
168 | _buildHTML: function () {
169 | var that = this;
170 |
171 | // prefix the animation string and store in animationParsed
172 | this._parseAnimation(this.animation, 'o');
173 | this._parseAnimation(this.closeAnimation, 'c');
174 | this._parseBgDismissAnimation(this.backgroundDismissAnimation);
175 | this._parseColumnClass(this.columnClass);
176 | this._parseTheme(this.theme);
177 | this._parseType(this.type);
178 |
179 | /*
180 | * Append html.
181 | */
182 | var template = $(this.template);
183 | template.find('.jconfirm-box').addClass(this.animationParsed).addClass(this.backgroundDismissAnimationParsed).addClass(this.typeParsed);
184 |
185 | if (this.typeAnimated)
186 | template.find('.jconfirm-box').addClass('jconfirm-type-animated');
187 |
188 | if (this.useBootstrap) {
189 | template.find('.jc-bs3-row').addClass(this.bootstrapClasses.row);
190 | template.find('.jc-bs3-row').addClass('justify-content-md-center justify-content-sm-center justify-content-xs-center justify-content-lg-center');
191 |
192 | template.find('.jconfirm-box-container').addClass(this.columnClassParsed);
193 |
194 | if (this.containerFluid)
195 | template.find('.jc-bs3-container').addClass(this.bootstrapClasses.containerFluid);
196 | else
197 | template.find('.jc-bs3-container').addClass(this.bootstrapClasses.container);
198 | } else {
199 | template.find('.jconfirm-box').css('width', this.boxWidth);
200 | }
201 |
202 | if (this.titleClass)
203 | template.find('.jconfirm-title-c').addClass(this.titleClass);
204 |
205 | template.addClass(this.themeParsed);
206 | var ariaLabel = 'jconfirm-box' + this._id;
207 | template.find('.jconfirm-box').attr('aria-labelledby', ariaLabel).attr('tabindex', -1);
208 | template.find('.jconfirm-content').attr('id', ariaLabel);
209 | if (this.bgOpacity != null)
210 | template.find('.jconfirm-bg').css('opacity', this.bgOpacity);
211 | if (this.rtl)
212 | template.addClass('jconfirm-rtl');
213 |
214 | this.$el = template.appendTo(this.container);
215 | this.$jconfirmBoxContainer = this.$el.find('.jconfirm-box-container');
216 | this.$jconfirmBox = this.$body = this.$el.find('.jconfirm-box');
217 | this.$jconfirmBg = this.$el.find('.jconfirm-bg');
218 | this.$title = this.$el.find('.jconfirm-title');
219 | this.$titleContainer = this.$el.find('.jconfirm-title-c');
220 | this.$content = this.$el.find('div.jconfirm-content');
221 | this.$contentPane = this.$el.find('.jconfirm-content-pane');
222 | this.$icon = this.$el.find('.jconfirm-icon-c');
223 | this.$closeIcon = this.$el.find('.jconfirm-closeIcon');
224 | // this.$content.css(this._getCSS(this.animationSpeed, this.animationBounce));
225 | this.$btnc = this.$el.find('.jconfirm-buttons');
226 | this.$scrollPane = this.$el.find('.jconfirm-scrollpane');
227 |
228 | // for loading content via URL
229 | this._contentReady = $.Deferred();
230 | this._modalReady = $.Deferred();
231 |
232 | this.setTitle();
233 | this.setIcon();
234 | this._setButtons();
235 | this._parseContent();
236 | this.initDraggable();
237 |
238 | if (this.isAjax)
239 | this.showLoading(false);
240 |
241 | $.when(this._contentReady, this._modalReady).then(function () {
242 | if (that.isAjaxLoading)
243 | setTimeout(function () {
244 | that.isAjaxLoading = false;
245 | that.setContent();
246 | that.setTitle();
247 | that.setIcon();
248 | setTimeout(function () {
249 | that.hideLoading(false);
250 | }, 100);
251 | if (typeof that.onContentReady == 'function')
252 | that.onContentReady();
253 | }, 50);
254 | else {
255 | that.setContent();
256 | that.setTitle();
257 | that.setIcon();
258 | if (typeof that.onContentReady == 'function')
259 | that.onContentReady();
260 | }
261 |
262 | // start countdown after content has loaded.
263 | if (that.autoClose)
264 | that._startCountDown();
265 | });
266 |
267 | // initial hash for comparison
268 | that._contentHash = this._hash(that.$content.html());
269 | that._contentHeight = this.$content.height();
270 |
271 | this._watchContent();
272 | this.setDialogCenter();
273 |
274 | if (this.animation == 'none') {
275 | this.animationSpeed = 1;
276 | this.animationBounce = 1;
277 | }
278 |
279 | this.$body.css(this._getCSS(this.animationSpeed, this.animationBounce));
280 | this.$contentPane.css(this._getCSS(this.animationSpeed, 1));
281 | this.$jconfirmBg.css(this._getCSS(this.animationSpeed, 1));
282 | },
283 | _typePrefix: 'jconfirm-type-',
284 | typeParsed: '',
285 | _parseType: function (type) {
286 | this.typeParsed = this._typePrefix + type;
287 | },
288 | setType: function (type) {
289 | var oldClass = this.typeParsed;
290 | this._parseType(type);
291 | this.$jconfirmBox.removeClass(oldClass).addClass(this.typeParsed);
292 | },
293 | themeParsed: '',
294 | _themePrefix: 'jconfirm-',
295 | setTheme: function (theme) {
296 | var previous = this.theme;
297 | this.theme = theme || this.theme;
298 | this._parseTheme(this.theme);
299 | if (previous)
300 | this.$el.removeClass(previous);
301 | this.$el.addClass(this.themeParsed);
302 | this.theme = theme;
303 | },
304 | _parseTheme: function (theme) {
305 | var that = this;
306 | theme = theme.split(',');
307 | $.each(theme, function (k, a) {
308 | if (a.indexOf(that._themePrefix) == -1)
309 | theme[k] = that._themePrefix + $.trim(a);
310 | });
311 | this.themeParsed = theme.join(' ').toLowerCase();
312 | },
313 | backgroundDismissAnimationParsed: '',
314 | _bgDismissPrefix: 'jconfirm-hilight-',
315 | _parseBgDismissAnimation: function (bgDismissAnimation) {
316 | var animation = bgDismissAnimation.split(',');
317 | var that = this;
318 | $.each(animation, function (k, a) {
319 | if (a.indexOf(that._bgDismissPrefix) == -1)
320 | animation[k] = that._bgDismissPrefix + $.trim(a);
321 | });
322 | this.backgroundDismissAnimationParsed = animation.join(' ').toLowerCase();
323 | },
324 | animationParsed: '',
325 | closeAnimationParsed: '',
326 | _animationPrefix: 'jconfirm-animation-',
327 | setAnimation: function (animation) {
328 | this.animation = animation || this.animation;
329 | this._parseAnimation(this.animation, 'o');
330 | },
331 | _parseAnimation: function (animation, which) {
332 | which = which || 'o'; // parse what animation and store where. open or close?
333 | var animations = animation.split(',');
334 | var that = this;
335 | $.each(animations, function (k, a) {
336 | if (a.indexOf(that._animationPrefix) == -1)
337 | animations[k] = that._animationPrefix + $.trim(a);
338 | });
339 | var a_string = animations.join(' ').toLowerCase();
340 | if (which == 'o')
341 | this.animationParsed = a_string;
342 | else
343 | this.closeAnimationParsed = a_string;
344 |
345 | return a_string;
346 | },
347 | setCloseAnimation: function (closeAnimation) {
348 | this.closeAnimation = closeAnimation || this.closeAnimation;
349 | this._parseAnimation(this.closeAnimation, 'c');
350 | },
351 | setAnimationSpeed: function (speed) {
352 | this.animationSpeed = speed || this.animationSpeed;
353 | // this.$body.css(this._getCSS(this.animationSpeed, this.animationBounce));
354 | },
355 | columnClassParsed: '',
356 | setColumnClass: function (colClass) {
357 | if (!this.useBootstrap) {
358 | console.warn("cannot set columnClass, useBootstrap is set to false");
359 | return;
360 | }
361 | this.columnClass = colClass || this.columnClass;
362 | this._parseColumnClass(this.columnClass);
363 | this.$jconfirmBoxContainer.addClass(this.columnClassParsed);
364 | },
365 | setBoxWidth: function () {
366 | if (this.useBootstrap) {
367 | console.warn("cannot set boxWidth, useBootstrap is set to true");
368 | return;
369 | }
370 | this.$jconfirmBox.css('width', this.boxWidth);
371 | },
372 | _parseColumnClass: function (colClass) {
373 | colClass = colClass.toLowerCase();
374 | var p;
375 | switch (colClass) {
376 | case 'xl':
377 | case 'xlarge':
378 | p = 'col-md-12';
379 | break;
380 | case 'l':
381 | case 'large':
382 | p = 'col-md-8 col-md-offset-2';
383 | break;
384 | case 'm':
385 | case 'medium':
386 | p = 'col-md-6 col-md-offset-3';
387 | break;
388 | case 's':
389 | case 'small':
390 | p = 'col-md-4 col-md-offset-4';
391 | break;
392 | case 'xs':
393 | case 'xsmall':
394 | p = 'col-md-2 col-md-offset-5';
395 | break;
396 | default:
397 | p = colClass;
398 | }
399 | this.columnClassParsed = p;
400 | },
401 | initDraggable: function () {
402 | var that = this;
403 | var $t = this.$titleContainer;
404 |
405 | this.resetDrag();
406 | if (this.draggable) {
407 | $t.addClass('jconfirm-hand');
408 | $t.on('mousedown', function (e) {
409 | that.mouseX = e.clientX;
410 | that.mouseY = e.clientY;
411 | that.isDrag = true;
412 | });
413 | $(window).on('mousemove.' + this._id, function (e) {
414 | if (that.isDrag) {
415 | that.movingX = e.clientX - that.mouseX + that.initialX;
416 | that.movingY = e.clientY - that.mouseY + that.initialY;
417 | that.setDrag();
418 | }
419 | });
420 |
421 | $(window).on('mouseup.' + this._id, function () {
422 | if (that.isDrag) {
423 | that.isDrag = false;
424 | that.initialX = that.movingX;
425 | that.initialY = that.movingY;
426 | }
427 | })
428 | }
429 | },
430 | resetDrag: function () {
431 | this.isDrag = false;
432 | this.initialX = 0;
433 | this.initialY = 0;
434 | this.movingX = 0;
435 | this.movingY = 0;
436 | this.movingXCurrent = 0;
437 | this.movingYCurrent = 0;
438 | this.mouseX = 0;
439 | this.mouseY = 0;
440 | this.$jconfirmBoxContainer.css('transform', 'translate(' + 0 + 'px, ' + 0 + 'px)');
441 | },
442 | setDrag: function () {
443 | if (!this.draggable)
444 | return;
445 |
446 | this.alignMiddle = false;
447 | this._boxWidth = this.$jconfirmBox.outerWidth();
448 | var ww = $(window).width();
449 | var that = this;
450 | if (that.movingX % 2 == 0 || that.movingY % 2 == 0) {
451 | var tb = that._boxTopMargin - that.dragWindowGap;
452 |
453 | if (tb + that.movingY < 0) {
454 | that.movingY = -tb;
455 | } else {
456 | that.movingYCurrent = that.movingY;
457 | }
458 | var lb = (ww / 2) - that._boxWidth / 2;
459 | var rb = (ww / 2) + (that._boxWidth / 2) - that._boxWidth;
460 | rb -= that.dragWindowGap;
461 | lb -= that.dragWindowGap;
462 |
463 | if (lb + that.movingX < 0) {
464 | that.movingX = -lb;
465 | } else if (rb - that.movingX < 0) {
466 | that.movingX = rb;
467 | } else {
468 | that.movingXCurrent = that.movingX;
469 | }
470 |
471 | that.$jconfirmBoxContainer.css('transform', 'translate(' + that.movingX + 'px, ' + that.movingY + 'px)');
472 | }
473 | },
474 | _hash: function (a) {
475 | var string = a.toString();
476 | var h = 0;
477 | if (string.length == 0) return h;
478 | for (var i = 0; i < string.length; i++) {
479 | var c = string.toString().charCodeAt(i);
480 | h = ((h << 5) - h) + c;
481 | h = h & h; // Convert to 32bit integer
482 | }
483 | return h;
484 | },
485 | _watchContent: function () {
486 | var that = this;
487 | if (this._timer) clearInterval(this._timer);
488 | this._timer = setInterval(function () {
489 | var now = that._hash(that.$content.html());
490 | var nowHeight = that.$content.height();
491 | if (that._contentHash != now || that._contentHeight != nowHeight) {
492 | that._contentHash = now;
493 | that._contentHeight = nowHeight;
494 | that.setDialogCenter();
495 | that._imagesLoaded();
496 | }
497 | }, this.watchInterval);
498 | },
499 | _hilightAnimating: false,
500 | _hiLightModal: function () {
501 | var that = this;
502 | if (this._hilightAnimating)
503 | return;
504 |
505 | that.$body.addClass('hilight');
506 | // var duration = parseFloat(that.$body.css('animation-duration')) || 0;
507 | var duration = 2; // 2 seconds default
508 | this._hilightAnimating = true;
509 | setTimeout(function () {
510 | that._hilightAnimating = false;
511 | that.$body.removeClass('hilight');
512 | }, duration * 1000);
513 | },
514 | _bindEvents: function () {
515 | var that = this;
516 | this.boxClicked = false;
517 |
518 | this.$scrollPane.click(function (e) { // Ignore propagated clicks
519 | if (!that.boxClicked) { // Background clicked
520 | /*
521 | If backgroundDismiss is a function and its return value is truthy
522 | proceed to close the modal.
523 | */
524 | var buttonName = false;
525 | var shouldClose = false;
526 | var str;
527 |
528 | if (typeof that.backgroundDismiss == 'function')
529 | str = that.backgroundDismiss();
530 | else
531 | str = that.backgroundDismiss;
532 |
533 | if (typeof str == 'string' && typeof that.buttons[str] != 'undefined') {
534 | buttonName = str;
535 | shouldClose = false;
536 | } else if (typeof str == 'undefined' || !!(str) == true) {
537 | shouldClose = true;
538 | } else {
539 | shouldClose = false;
540 | }
541 |
542 | if (buttonName) {
543 | var btnResponse = that.buttons[buttonName].action.apply(that);
544 | shouldClose = (typeof btnResponse == 'undefined') || !!(btnResponse);
545 | }
546 |
547 | if (shouldClose)
548 | that.close();
549 | else
550 | that._hiLightModal();
551 | }
552 | that.boxClicked = false;
553 | });
554 |
555 | this.$jconfirmBox.click(function (e) {
556 | that.boxClicked = true;
557 | });
558 |
559 | var isKeyDown = false;
560 | $(window).on('jcKeyDown.' + that._id, function (e) {
561 | if (!isKeyDown) {
562 | isKeyDown = true;
563 | }
564 | });
565 | $(window).on('keyup.' + that._id, function (e) {
566 | if (isKeyDown) {
567 | that.reactOnKey(e);
568 | isKeyDown = false;
569 | }
570 | });
571 |
572 | $(window).on('resize.' + this._id, function () {
573 | that.setDialogCenter(true);
574 | setTimeout(function () {
575 | that.resetDrag();
576 | }, 100);
577 | });
578 | },
579 | _cubic_bezier: '0.36, 0.55, 0.19',
580 | _getCSS: function (speed, bounce) {
581 | return {
582 | '-webkit-transition-duration': speed / 1000 + 's',
583 | 'transition-duration': speed / 1000 + 's',
584 | '-webkit-transition-timing-function': 'cubic-bezier(' + this._cubic_bezier + ', ' + bounce + ')',
585 | 'transition-timing-function': 'cubic-bezier(' + this._cubic_bezier + ', ' + bounce + ')'
586 | };
587 | },
588 | _imagesLoaded: function () {
589 | // detect if the image is loaded by checking on its height.
590 | var that = this;
591 | if (that.imageLoadInterval)
592 | clearInterval(that.imageLoadInterval);
593 |
594 | $.each(this.$content.find('img:not(.loaded)'), function (i, a) {
595 | that.imageLoadInterval = setInterval(function () {
596 | var h = $(a).css('height');
597 | if (h !== '0px') {
598 | $(a).addClass('loaded');
599 | clearInterval(that.imageLoadInterval);
600 | that.setDialogCenter();
601 | }
602 | }, 40);
603 | });
604 | },
605 | _setButtons: function () {
606 | var that = this;
607 | /*
608 | * Settings up buttons
609 | */
610 |
611 | var total_buttons = 0;
612 | if (typeof this.buttons !== 'object')
613 | this.buttons = {};
614 |
615 | $.each(this.buttons, function (key, button) {
616 | total_buttons += 1;
617 | if (typeof button === 'function') {
618 | that.buttons[key] = button = {
619 | action: button
620 | };
621 | }
622 |
623 | that.buttons[key].text = button.text || key;
624 | that.buttons[key].btnClass = button.btnClass || 'btn-default';
625 | that.buttons[key].action = button.action || function () {
626 | };
627 | that.buttons[key].keys = button.keys || [];
628 | that.buttons[key].isHidden = button.isHidden || false;
629 | that.buttons[key].isDisabled = button.isDisabled || false;
630 |
631 | $.each(that.buttons[key].keys, function (i, a) {
632 | that.buttons[key].keys[i] = a.toLowerCase();
633 | });
634 |
635 | var button_element = $('')
636 | .html(that.buttons[key].text)
637 | .addClass(that.buttons[key].btnClass)
638 | .prop('disabled', that.buttons[key].isDisabled)
639 | .css('display', that.buttons[key].isHidden ? 'none' : '')
640 | .click(function (e) {
641 | e.preventDefault();
642 | var res = that.buttons[key].action.apply(that);
643 | that.onAction(key);
644 | that._stopCountDown();
645 | if (typeof res === 'undefined' || res)
646 | that.close();
647 | });
648 |
649 | that.buttons[key].el = button_element;
650 | that.buttons[key].setText = function (text) {
651 | button_element.html(text);
652 | };
653 | that.buttons[key].addClass = function (className) {
654 | button_element.addClass(className);
655 | };
656 | that.buttons[key].removeClass = function (className) {
657 | button_element.removeClass(className);
658 | };
659 | that.buttons[key].disable = function () {
660 | that.buttons[key].isDisabled = true;
661 | button_element.prop('disabled', true);
662 | };
663 | that.buttons[key].enable = function () {
664 | that.buttons[key].isDisabled = false;
665 | button_element.prop('disabled', false);
666 | };
667 | that.buttons[key].show = function () {
668 | that.buttons[key].isHidden = false;
669 | button_element.css('display', '');
670 | that.setDialogCenter();
671 | };
672 | that.buttons[key].hide = function () {
673 | that.buttons[key].isHidden = true;
674 | button_element.css('display', 'none');
675 | that.setDialogCenter();
676 | };
677 | /*
678 | Buttons are prefixed with $_ or $$ for quick access
679 | */
680 | that['$_' + key] = that['$$' + key] = button_element;
681 | that.$btnc.append(button_element);
682 | });
683 |
684 | if (total_buttons === 0) this.$btnc.hide();
685 | if (this.closeIcon === null && total_buttons === 0) {
686 | /*
687 | in case when no buttons are present & closeIcon is null, closeIcon is set to true,
688 | set closeIcon to true to explicitly tell to hide the close icon
689 | */
690 | this.closeIcon = true;
691 | }
692 |
693 | if (this.closeIcon) {
694 | if (this.closeIconClass) {
695 | // user requires a custom class.
696 | var closeHtml = '';
697 | this.$closeIcon.html(closeHtml);
698 | }
699 |
700 | this.$closeIcon.click(function (e) {
701 | e.preventDefault();
702 |
703 | var buttonName = false;
704 | var shouldClose = false;
705 | var str;
706 |
707 | if (typeof that.closeIcon == 'function') {
708 | str = that.closeIcon();
709 | } else {
710 | str = that.closeIcon;
711 | }
712 |
713 | if (typeof str == 'string' && typeof that.buttons[str] != 'undefined') {
714 | buttonName = str;
715 | shouldClose = false;
716 | } else if (typeof str == 'undefined' || !!(str) == true) {
717 | shouldClose = true;
718 | } else {
719 | shouldClose = false;
720 | }
721 | if (buttonName) {
722 | var btnResponse = that.buttons[buttonName].action.apply(that);
723 | shouldClose = (typeof btnResponse == 'undefined') || !!(btnResponse);
724 | }
725 | if (shouldClose) {
726 | that.close();
727 | }
728 | });
729 | this.$closeIcon.show();
730 | } else {
731 | this.$closeIcon.hide();
732 | }
733 | },
734 | setTitle: function (string, force) {
735 | force = force || false;
736 |
737 | if (typeof string !== 'undefined')
738 | if (typeof string == 'string')
739 | this.title = string;
740 | else if (typeof string == 'function') {
741 | if (typeof string.promise == 'function')
742 | console.error('Promise was returned from title function, this is not supported.');
743 |
744 | var response = string();
745 | if (typeof response == 'string')
746 | this.title = response;
747 | else
748 | this.title = false;
749 | } else
750 | this.title = false;
751 |
752 | if (this.isAjaxLoading && !force)
753 | return;
754 |
755 | this.$title.html(this.title || '');
756 | },
757 | setIcon: function (iconClass, force) {
758 | force = force || false;
759 |
760 | if (typeof iconClass !== 'undefined')
761 | if (typeof iconClass == 'string')
762 | this.icon = iconClass;
763 | else if (typeof iconClass === 'function') {
764 | var response = iconClass();
765 | if (typeof response == 'string')
766 | this.icon = response;
767 | else
768 | this.icon = false;
769 | }
770 | else
771 | this.icon = false;
772 |
773 | if (this.isAjaxLoading && !force)
774 | return;
775 |
776 | this.$icon.html(this.icon ? '' : '');
777 | },
778 | setContentPrepend: function (string, force) {
779 | this.contentParsed = string + this.contentParsed;
780 | if (this.isAjaxLoading && !force)
781 | return;
782 |
783 | this.$content.prepend(string);
784 | },
785 | setContentAppend: function (string, force) {
786 | this.contentParsed = this.contentParsed + string;
787 | if (this.isAjaxLoading && !force)
788 | return;
789 |
790 | this.$content.append(string);
791 | },
792 | setContent: function (string, force) {
793 | force = force || false;
794 | var that = this;
795 | this.contentParsed = (typeof string == 'undefined') ? this.contentParsed : string;
796 | if (this.isAjaxLoading && !force)
797 | return;
798 |
799 | this.$content.html(this.contentParsed);
800 | this.setDialogCenter();
801 | setTimeout(function () {
802 | that.$body.find('input[autofocus]:visible:first').focus();
803 | }, 100);
804 | },
805 | loadingSpinner: false,
806 | showLoading: function (disableButtons) {
807 | this.loadingSpinner = true;
808 | this.$jconfirmBox.addClass('loading');
809 | if (disableButtons)
810 | this.$btnc.find('button').prop('disabled', true);
811 |
812 | this.setDialogCenter();
813 | },
814 | hideLoading: function (enableButtons) {
815 | this.loadingSpinner = false;
816 | this.$jconfirmBox.removeClass('loading');
817 | if (enableButtons)
818 | this.$btnc.find('button').prop('disabled', false);
819 |
820 | this.setDialogCenter();
821 | },
822 | ajaxResponse: false,
823 | contentParsed: '',
824 | isAjax: false,
825 | isAjaxLoading: false,
826 | _parseContent: function () {
827 | var that = this;
828 | var e = ' ';
829 |
830 | if (typeof this.content == 'function') {
831 | var res = this.content.apply(this);
832 | if (typeof res == 'string') {
833 | this.content = res;
834 | }
835 | else if (typeof res == 'object' && typeof res.always == 'function') {
836 | // this is ajax loading via promise
837 | this.isAjax = true;
838 | this.isAjaxLoading = true;
839 | res.always(function (data, status, xhr) {
840 | that.ajaxResponse = {
841 | data: data,
842 | status: status,
843 | xhr: xhr
844 | };
845 | that._contentReady.resolve(data, status, xhr);
846 | if (typeof that.contentLoaded == 'function')
847 | that.contentLoaded(data, status, xhr);
848 | });
849 | this.content = e;
850 | } else {
851 | this.content = e;
852 | }
853 | }
854 |
855 | if (typeof this.content == 'string' && this.content.substr(0, 4).toLowerCase() === 'url:') {
856 | this.isAjax = true;
857 | this.isAjaxLoading = true;
858 | var u = this.content.substring(4, this.content.length);
859 | $.get(u).done(function (html) {
860 | that.contentParsed = html;
861 | }).always(function (data, status, xhr) {
862 | that.ajaxResponse = {
863 | data: data,
864 | status: status,
865 | xhr: xhr
866 | };
867 | that._contentReady.resolve(data, status, xhr);
868 | if (typeof that.contentLoaded == 'function')
869 | that.contentLoaded(data, status, xhr);
870 | });
871 | }
872 |
873 | if (!this.content)
874 | this.content = e;
875 |
876 | if (!this.isAjax) {
877 | this.contentParsed = this.content;
878 | this.setContent(this.contentParsed);
879 | that._contentReady.resolve();
880 | }
881 | },
882 | _stopCountDown: function () {
883 | clearInterval(this.autoCloseInterval);
884 | if (this.$cd)
885 | this.$cd.remove();
886 | },
887 | _startCountDown: function () {
888 | var that = this;
889 | var opt = this.autoClose.split('|');
890 | if (opt.length !== 2) {
891 | console.error('Invalid option for autoClose. example \'close|10000\'');
892 | return false;
893 | }
894 |
895 | var button_key = opt[0];
896 | var time = parseInt(opt[1]);
897 | if (typeof this.buttons[button_key] === 'undefined') {
898 | console.error('Invalid button key \'' + button_key + '\' for autoClose');
899 | return false;
900 | }
901 |
902 | var seconds = Math.ceil(time / 1000);
903 | this.$cd = $(' (' + seconds + ')')
904 | .appendTo(this['$_' + button_key]);
905 |
906 | this.autoCloseInterval = setInterval(function () {
907 | that.$cd.html(' (' + (seconds -= 1) + ') ');
908 | if (seconds <= 0) {
909 | that['$$' + button_key].trigger('click');
910 | that._stopCountDown();
911 | }
912 | }, 1000);
913 | },
914 | _getKey: function (key) {
915 | // very necessary keys.
916 | switch (key) {
917 | case 192:
918 | return 'tilde';
919 | case 13:
920 | return 'enter';
921 | case 16:
922 | return 'shift';
923 | case 9:
924 | return 'tab';
925 | case 20:
926 | return 'capslock';
927 | case 17:
928 | return 'ctrl';
929 | case 91:
930 | return 'win';
931 | case 18:
932 | return 'alt';
933 | case 27:
934 | return 'esc';
935 | case 32:
936 | return 'space';
937 | }
938 |
939 | // only trust alphabets with this.
940 | var initial = String.fromCharCode(key);
941 | if (/^[A-z0-9]+$/.test(initial))
942 | return initial.toLowerCase();
943 | else
944 | return false;
945 | },
946 | reactOnKey: function (e) {
947 | var that = this;
948 |
949 | /*
950 | Prevent keyup event if the dialog is not last!
951 | */
952 | var a = $('.jconfirm');
953 | if (a.eq(a.length - 1)[0] !== this.$el[0])
954 | return false;
955 |
956 | var key = e.which;
957 | /*
958 | Do not react if Enter or Space is pressed on input elements
959 | */
960 | if (this.$content.find(':input').is(':focus') && /13|32/.test(key))
961 | return false;
962 |
963 | var keyChar = this._getKey(key);
964 |
965 | // If esc is pressed
966 | if (keyChar === 'esc' && this.escapeKey) {
967 | if (this.escapeKey === true) {
968 | this.$scrollPane.trigger('click');
969 | }
970 | else if (typeof this.escapeKey === 'string' || typeof this.escapeKey === 'function') {
971 | var buttonKey;
972 | if (typeof this.escapeKey === 'function') {
973 | buttonKey = this.escapeKey();
974 | } else {
975 | buttonKey = this.escapeKey;
976 | }
977 |
978 | if (buttonKey)
979 | if (typeof this.buttons[buttonKey] === 'undefined') {
980 | console.warn('Invalid escapeKey, no buttons found with key ' + buttonKey);
981 | } else {
982 | this['$_' + buttonKey].trigger('click');
983 | }
984 | }
985 | }
986 |
987 | // check if any button is listening to this key.
988 | $.each(this.buttons, function (key, button) {
989 | if (button.keys.indexOf(keyChar) != -1) {
990 | that['$_' + key].trigger('click');
991 | }
992 | });
993 | },
994 | _boxTopMargin: 0,
995 | _boxBottomMargin: 0,
996 | _boxWidth: 0,
997 | setDialogCenter: function () {
998 | var contentHeight;
999 | var paneHeight;
1000 | var style;
1001 | contentHeight = 0;
1002 | paneHeight = 0;
1003 | if (this.$contentPane.css('display') != 'none') {
1004 | contentHeight = this.$content.outerHeight() || 0;
1005 | paneHeight = this.$contentPane.height() || 0;
1006 | }
1007 |
1008 | // if the child has margin top
1009 | var children = this.$content.children();
1010 | if (children.length != 0) {
1011 | var marginTopChild = parseInt(children.eq(0).css('margin-top'));
1012 | if (marginTopChild)
1013 | contentHeight += marginTopChild;
1014 | }
1015 |
1016 | if (paneHeight == 0) {
1017 | paneHeight = contentHeight;
1018 | }
1019 |
1020 | var windowHeight = $(window).height();
1021 | var boxHeight;
1022 |
1023 | boxHeight = (this.$body.outerHeight() - paneHeight) + contentHeight;
1024 |
1025 | var topMargin = (windowHeight - boxHeight) / 2;
1026 | if (boxHeight > (windowHeight - (this.offsetTop + this.offsetBottom)) || !this.alignMiddle) {
1027 | style = {
1028 | 'margin-top': this.offsetTop,
1029 | 'margin-bottom': this.offsetBottom
1030 | };
1031 | this._boxTopMargin = this.offsetTop;
1032 | this._boxBottomMargin = this.offsetBottom;
1033 | $('body').addClass('jconfirm-no-scroll-' + this._id);
1034 | } else {
1035 | style = {
1036 | 'margin-top': topMargin,
1037 | 'margin-bottom': this.offsetBottom
1038 | };
1039 | this._boxTopMargin = topMargin;
1040 | this._boxBottomMargin = this.offsetBottom;
1041 | $('body').removeClass('jconfirm-no-scroll-' + this._id);
1042 | }
1043 |
1044 | this.$contentPane.css({
1045 | 'height': contentHeight
1046 | }).scrollTop(0);
1047 | this.$body.css(style);
1048 |
1049 | this.setDrag();
1050 | },
1051 | _unwatchContent: function () {
1052 | clearInterval(this._timer);
1053 | },
1054 | close: function () {
1055 | var that = this;
1056 |
1057 | if (typeof this.onClose === 'function')
1058 | this.onClose();
1059 |
1060 | this._unwatchContent();
1061 | clearInterval(this.imageLoadInterval);
1062 |
1063 | /*
1064 | unbind the window resize & keyup event.
1065 | */
1066 | $(window).unbind('resize.' + this._id);
1067 | $(window).unbind('keyup.' + this._id);
1068 | $(window).unbind('jcKeyDown.' + this._id);
1069 |
1070 | if (this.draggable) {
1071 | $(window).unbind('mousemove.' + this._id);
1072 | $(window).unbind('mouseup.' + this._id);
1073 | this.$titleContainer.unbind('mousedown');
1074 | }
1075 | $('body').removeClass('jconfirm-no-scroll-' + this._id);
1076 | this.$body.addClass(this.closeAnimationParsed);
1077 | this.$jconfirmBg.addClass('jconfirm-bg-h');
1078 | var closeTimer = (this.closeAnimation == 'none') ? 1 : this.animationSpeed;
1079 | that.$el.removeClass(that.loadedClass);
1080 | setTimeout(function () {
1081 | that.$el.remove();
1082 |
1083 | var l = jconfirm.instances;
1084 | var i = jconfirm.instances.length - 1;
1085 | for (i; i >= 0; i--) {
1086 | if (jconfirm.instances[i]._id == that._id) {
1087 | jconfirm.instances.splice(i, 1);
1088 | }
1089 | }
1090 |
1091 | // Focusing a element, scrolls automatically to that element.
1092 | // no instances should be open, lastFocused should be true, the lastFocused element must exists in DOM
1093 | if (!jconfirm.instances.length) {
1094 | if (that.scrollToPreviousElement && jconfirm.lastFocused && jconfirm.lastFocused.length && $.contains(document, jconfirm.lastFocused[0])) {
1095 | var $lf = jconfirm.lastFocused;
1096 | if (that.scrollToPreviousElementAnimate) {
1097 | var st = $(window).scrollTop();
1098 | var ot = jconfirm.lastFocused.offset().top;
1099 | var wh = $(window).height();
1100 | if (!(ot > st && ot < (st + wh))) {
1101 | var scrollTo = (ot - Math.round((wh / 3)));
1102 | $('html, body').animate({
1103 | scrollTop: scrollTo
1104 | }, that.animationSpeed, 'swing', function () {
1105 | // gracefully scroll and then focus.
1106 | $lf.focus();
1107 | });
1108 | } else {
1109 | // the element to be focused is already in view.
1110 | $lf.focus();
1111 | }
1112 | } else {
1113 | $lf.focus();
1114 | }
1115 | jconfirm.lastFocused = false;
1116 | }
1117 | }
1118 |
1119 | if (typeof that.onDestroy == 'function')
1120 | that.onDestroy();
1121 |
1122 | }, closeTimer * 0.40);
1123 |
1124 | return true;
1125 | },
1126 | open: function () {
1127 | if (this.isOpen())
1128 | return false;
1129 |
1130 | // var that = this;
1131 | this._buildHTML();
1132 | this._bindEvents();
1133 | this._open();
1134 |
1135 | return true;
1136 | },
1137 | _open: function () {
1138 | var that = this;
1139 | if (typeof that.onOpenBefore == 'function')
1140 | that.onOpenBefore();
1141 | this.$body.removeClass(this.animationParsed);
1142 | this.$jconfirmBg.removeClass('jconfirm-bg-h');
1143 | this.$body.focus();
1144 | setTimeout(function () {
1145 | that.$body.css(that._getCSS(that.animationSpeed, 1));
1146 | that.$body.css({
1147 | 'transition-property': that.$body.css('transition-property') + ', margin'
1148 | });
1149 | that._modalReady.resolve();
1150 | if (typeof that.onOpen === 'function')
1151 | that.onOpen();
1152 |
1153 | that.$el.addClass(that.loadedClass);
1154 | }, this.animationSpeed);
1155 | },
1156 | loadedClass: 'jconfirm-open',
1157 | isClosed: function () {
1158 | return !this.$el || this.$el.css('display') === '';
1159 | },
1160 | isOpen: function () {
1161 | return !this.isClosed();
1162 | },
1163 | toggle: function () {
1164 | if (!this.isOpen())
1165 | this.open();
1166 | else
1167 | this.close();
1168 | }
1169 | };
1170 |
1171 | jconfirm.instances = [];
1172 | jconfirm.lastFocused = false;
1173 | jconfirm.pluginDefaults = {
1174 | template: '' +
1175 | '',
1193 | title: 'Hello',
1194 | titleClass: '',
1195 | type: 'default',
1196 | typeAnimated: true,
1197 | draggable: false,
1198 | alignMiddle: true,
1199 | content: 'Are you sure to continue?',
1200 | buttons: {},
1201 | defaultButtons: {
1202 | ok: {
1203 | action: function () {
1204 | }
1205 | },
1206 | close: {
1207 | action: function () {
1208 | }
1209 | }
1210 | },
1211 | contentLoaded: function () {
1212 | },
1213 | icon: '',
1214 | lazyOpen: false,
1215 | bgOpacity: null,
1216 | theme: 'light',
1217 | animation: 'zoom',
1218 | closeAnimation: 'scale',
1219 | animationSpeed: 400,
1220 | animationBounce: 1.2,
1221 | escapeKey: true,
1222 | rtl: false,
1223 | container: 'body',
1224 | containerFluid: false,
1225 | backgroundDismiss: false,
1226 | backgroundDismissAnimation: 'shake',
1227 | autoClose: false,
1228 | closeIcon: null,
1229 | closeIconClass: false,
1230 | watchInterval: 100,
1231 | columnClass: 'col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3 col-xs-10 col-xs-offset-1',
1232 | boxWidth: '50%',
1233 | scrollToPreviousElement: true,
1234 | scrollToPreviousElementAnimate: true,
1235 | useBootstrap: true,
1236 | offsetTop: 50,
1237 | offsetBottom: 50,
1238 | dragWindowGap: 15,
1239 | bootstrapClasses: {
1240 | container: 'container',
1241 | containerFluid: 'container-fluid',
1242 | row: 'row'
1243 | },
1244 | onContentReady: function () {
1245 |
1246 | },
1247 | onOpenBefore: function () {
1248 |
1249 | },
1250 | onOpen: function () {
1251 |
1252 | },
1253 | onClose: function () {
1254 |
1255 | },
1256 | onDestroy: function () {
1257 |
1258 | },
1259 | onAction: function () {
1260 |
1261 | }
1262 | };
1263 |
1264 | /**
1265 | * This refers to the issue #241 and #246
1266 | *
1267 | * Problem:
1268 | * Button A is clicked (keydown) using the Keyboard ENTER key
1269 | * A opens the jconfirm modal B,
1270 | * B has registered ENTER key for one of its button C
1271 | * A is released (keyup), B gets the keyup event and triggers C.
1272 | *
1273 | * Solution:
1274 | * Register a global keydown event, that tells jconfirm if the keydown originated inside jconfirm
1275 | */
1276 | var keyDown = false;
1277 | $(window).on('keydown', function (e) {
1278 | if (!keyDown) {
1279 | var $target = $(e.target);
1280 | var pass = false;
1281 | if ($target.closest('.jconfirm-box').length)
1282 | pass = true;
1283 | if (pass)
1284 | $(window).trigger('jcKeyDown');
1285 |
1286 | keyDown = true;
1287 | }
1288 | });
1289 | $(window).on('keyup', function (e) {
1290 | keyDown = false;
1291 | });
1292 | })(jQuery, window);
1293 |
--------------------------------------------------------------------------------
/servers/portforward/theme/style.css:
--------------------------------------------------------------------------------
1 | #YVSY * {
2 | font-family: 'Helvetica Neue','Hiragino Sans GB','Helvetica Neue','Hiragino Sans GB','Microsoft YaHei','Open Sans',sans-serif !important;
3 | color: #555;
4 | }
5 | #YVSY a {
6 | text-decoration: none;
7 | }
8 | #YVSY small {
9 | color: #999;
10 | }
11 | #YVSY ul, li {
12 | list-style: none;
13 | }
14 | #YVSY .fa {
15 | font-family: 'FontAwesome' !important;
16 | }
17 | #YVSY .mdi {
18 | font-family: "Material Design Icons" !important;
19 | }
20 | #YVSY .glyphicon {
21 | font-family: 'Glyphicons Halflings', 'Open Sans',sans-serif !important;
22 | }
23 | #YVSY .box {
24 | border: 1px solid #DDD;
25 | display:block;
26 | width:100%;
27 | border-radius: 4px;
28 | padding:20px;
29 | margin-bottom: 16px;
30 | }
31 | #YVSY .box:hover {
32 | border: 1px solid #337ab7;
33 | }
34 | #YVSY .boxTitle {
35 | font-weight:300;
36 | color:#9da2a6;
37 | margin-bottom:4px;
38 | }
39 | #YVSY .boxContent {
40 | color:#363b40;
41 | font-size:26px;
42 | font-weight:500;
43 | line-height:32px;
44 | }
45 | #YVSY .p-0 {
46 | padding: 0 !important;
47 | }
48 | #YVSY .p-20 {
49 | padding: 20px !important;
50 | }
51 | #YVSY .p-30 {
52 | padding: 30px !important;
53 | }
54 | #YVSY .p-l-0 {
55 | padding-left: 0 !important;
56 | }
57 | #YVSY .p-r-0 {
58 | padding-right: 0 !important;
59 | }
60 | #YVSY .p-t-0 {
61 | padding-top: 0 !important;
62 | }
63 | #YVSY .p-b-0 {
64 | padding-bottom: 0 !important;
65 | }
66 | #YVSY .p-t-10 {
67 | padding-top: 10px !important;
68 | }
69 | #YVSY .p-b-10 {
70 | padding-bottom: 10px !important;
71 | }
72 | #YVSY .p-l-r-10 {
73 | padding-left: 10px;
74 | padding-right: 10px;
75 | }
76 | #YVSY .m-0 {
77 | margin: 0 !important;
78 | }
79 | #YVSY .m-r-5 {
80 | margin-right: 5px !important;
81 | }
82 | #YVSY .m-r-10 {
83 | margin-right: 10px !important;
84 | }
85 | #YVSY .m-r-15 {
86 | margin-right: 15px !important;
87 | }
88 | #YVSY .m-l-5 {
89 | margin-left: 5px !important;
90 | }
91 | #YVSY .m-l-10 {
92 | margin-left: 10px !important;
93 | }
94 | #YVSY .m-l-15 {
95 | margin-left: 15px !important;
96 | }
97 | #YVSY .m-t-5 {
98 | margin-top: 5px !important;
99 | }
100 | #YVSY .m-t-0 {
101 | margin-top: 0 !important;
102 | }
103 | #YVSY .m-t-10 {
104 | margin-top: 10px !important;
105 | }
106 | #YVSY .m-t-15 {
107 | margin-top: 15px !important;
108 | }
109 | #YVSY .m-t-20 {
110 | margin-top: 20px !important;
111 | }
112 | #YVSY .m-t-30 {
113 | margin-top: 30px !important;
114 | }
115 | #YVSY .m-t-40 {
116 | margin-top: 40px !important;
117 | }
118 | #YVSY .m-t-50 {
119 | margin-top: 50px !important;
120 | }
121 | #YVSY .m-b-0 {
122 | margin-bottom: 0 !important;
123 | }
124 | #YVSY .m-b-5 {
125 | margin-bottom: 5px !important;
126 | }
127 | #YVSY .m-b-10 {
128 | margin-bottom: 10px !important;
129 | }
130 | #YVSY .m-b-15 {
131 | margin-bottom: 15px !important;
132 | }
133 | #YVSY .m-b-20 {
134 | margin-bottom: 20px !important;
135 | }
136 | #YVSY .m-b-25 {
137 | margin-bottom: 25px !important;
138 | }
139 | #YVSY .m-b-30 {
140 | margin-bottom: 30px !important;
141 | }
--------------------------------------------------------------------------------